组件库是低代码平台的核心资产,它决定了平台的功能边界和开发效率。本章将详细介绍如何设计和实现一个完整的组件库系统。

5.1 组件库架构设计

5.1.1 整体架构

graph TB
    A[组件库管理器] --> B[组件注册中心]
    A --> C[组件加载器]
    A --> D[组件版本管理]
    
    B --> E[内置组件]
    B --> F[第三方组件]
    B --> G[自定义组件]
    
    C --> H[动态加载]
    C --> I[懒加载]
    C --> J[预加载]
    
    D --> K[版本控制]
    D --> L[依赖管理]
    D --> M[兼容性检查]
    
    E --> N[基础组件]
    E --> O[布局组件]
    E --> P[表单组件]
    E --> Q[图表组件]

5.1.2 组件库管理器

// 组件库管理器
class ComponentLibraryManager {
  private libraries: Map<string, ComponentLibrary> = new Map();
  private componentRegistry: ComponentRegistry;
  private versionManager: VersionManager;
  private loader: ComponentLoader;
  private eventBus: EventBus;
  
  constructor(
    componentRegistry: ComponentRegistry,
    eventBus: EventBus
  ) {
    this.componentRegistry = componentRegistry;
    this.eventBus = eventBus;
    this.versionManager = new VersionManager();
    this.loader = new ComponentLoader(this.eventBus);
    
    this.initializeBuiltinLibraries();
  }

  // 注册组件库
  async registerLibrary(library: ComponentLibrary): Promise<void> {
    try {
      // 验证组件库
      await this.validateLibrary(library);
      
      // 检查版本兼容性
      this.versionManager.checkCompatibility(library);
      
      // 加载组件库
      await this.loader.loadLibrary(library);
      
      // 注册组件
      library.components.forEach(component => {
        this.componentRegistry.registerComponent(component);
      });
      
      // 存储组件库
      this.libraries.set(library.id, library);
      
      // 触发事件
      this.eventBus.emit('library:registered', library);
      
      console.log(`Component library "${library.name}" registered successfully`);
    } catch (error) {
      console.error(`Failed to register library "${library.name}":`, error);
      throw error;
    }
  }

  // 卸载组件库
  async unregisterLibrary(libraryId: string): Promise<void> {
    const library = this.libraries.get(libraryId);
    if (!library) {
      throw new Error(`Library "${libraryId}" not found`);
    }
    
    try {
      // 检查依赖
      this.checkLibraryDependencies(libraryId);
      
      // 卸载组件
      library.components.forEach(component => {
        this.componentRegistry.unregisterComponent(component.type);
      });
      
      // 卸载资源
      await this.loader.unloadLibrary(library);
      
      // 移除组件库
      this.libraries.delete(libraryId);
      
      // 触发事件
      this.eventBus.emit('library:unregistered', library);
      
      console.log(`Component library "${library.name}" unregistered successfully`);
    } catch (error) {
      console.error(`Failed to unregister library "${library.name}":`, error);
      throw error;
    }
  }

  // 获取组件库列表
  getLibraries(): ComponentLibrary[] {
    return Array.from(this.libraries.values());
  }

  // 获取组件库
  getLibrary(libraryId: string): ComponentLibrary | undefined {
    return this.libraries.get(libraryId);
  }

  // 搜索组件库
  searchLibraries(keyword: string): ComponentLibrary[] {
    const lowerKeyword = keyword.toLowerCase();
    return Array.from(this.libraries.values())
      .filter(library => 
        library.name.toLowerCase().includes(lowerKeyword) ||
        library.description.toLowerCase().includes(lowerKeyword) ||
        library.tags.some(tag => tag.toLowerCase().includes(lowerKeyword))
      );
  }

  // 更新组件库
  async updateLibrary(libraryId: string, newVersion: string): Promise<void> {
    const library = this.libraries.get(libraryId);
    if (!library) {
      throw new Error(`Library "${libraryId}" not found`);
    }
    
    try {
      // 获取新版本信息
      const newLibrary = await this.fetchLibraryVersion(libraryId, newVersion);
      
      // 检查兼容性
      this.versionManager.checkUpdateCompatibility(library, newLibrary);
      
      // 备份当前版本
      const backup = { ...library };```

## 5.3 组件注册与使用

### 5.3.1 组件注册

```typescript
// 注册内置组件
class ComponentRegistryInitializer {
  static async initializeBuiltinComponents(registry: ComponentRegistry): Promise<void> {
    try {
      // 注册基础组件
      await registry.registerComponent(TextComponent);
      await registry.registerComponent(ButtonComponent);
      await registry.registerComponent(InputComponent);
      
      // 注册布局组件
      await registry.registerComponent(ContainerComponent);
      await registry.registerComponent(GridComponent);
      
      console.log('内置组件注册完成');
    } catch (error) {
      console.error('组件注册失败:', error);
      throw error;
    }
  }
  
  static async loadExternalComponents(registry: ComponentRegistry, componentUrls: string[]): Promise<void> {
    const loadPromises = componentUrls.map(async (url) => {
      try {
        const response = await fetch(url);
        const componentDefinition = await response.json();
        await registry.registerComponent(componentDefinition);
        console.log(`外部组件加载成功: ${componentDefinition.name}`);
      } catch (error) {
        console.error(`外部组件加载失败: ${url}`, error);
      }
    });
    
    await Promise.allSettled(loadPromises);
  }
}

// 使用示例
const initializeComponentSystem = async () => {
  const registry = new ComponentRegistry();
  const loader = new ComponentLoader();
  
  // 初始化内置组件
  await ComponentRegistryInitializer.initializeBuiltinComponents(registry);
  
  // 加载外部组件
  const externalComponents = [
    '/api/components/chart-component.json',
    '/api/components/table-component.json',
    '/api/components/form-component.json'
  ];
  
  await ComponentRegistryInitializer.loadExternalComponents(registry, externalComponents);
  
  return { registry, loader };
};

5.3.2 组件使用示例

// 组件使用管理器
class ComponentUsageManager {
  private registry: ComponentRegistry;
  private loader: ComponentLoader;
  
  constructor(registry: ComponentRegistry, loader: ComponentLoader) {
    this.registry = registry;
    this.loader = loader;
  }
  
  // 创建组件实例
  async createComponentInstance(componentId: string, props: any = {}, container?: HTMLElement): Promise<ComponentInstance> {
    const definition = this.registry.getComponent(componentId);
    if (!definition) {
      throw new Error(`组件未找到: ${componentId}`);
    }
    
    const instance: ComponentInstance = {
      id: this.generateInstanceId(),
      componentId,
      definition,
      props: { ...definition.defaultProps, ...props },
      element: null,
      children: [],
      parent: null,
      events: {},
      state: {}
    };
    
    // 渲染组件
    if (container) {
      await this.renderComponent(instance, container);
    }
    
    return instance;
  }
  
  // 渲染组件
  async renderComponent(instance: ComponentInstance, container: HTMLElement): Promise<void> {
    const { definition, props, events } = instance;
    
    if (definition.renderer && definition.renderer.render) {
      // 使用自定义渲染器
      instance.element = definition.renderer.render(props, events);
    } else {
      // 使用默认渲染器
      instance.element = this.createDefaultElement(definition, props);
    }
    
    if (instance.element) {
      container.appendChild(instance.element);
      
      // 应用样式
      if (definition.styles) {
        this.applyStyles(definition.styles, instance.element);
      }
    }
  }
  
  // 更新组件属性
  updateComponentProps(instance: ComponentInstance, newProps: any): void {
    instance.props = { ...instance.props, ...newProps };
    
    if (instance.definition.renderer && instance.definition.renderer.update && instance.element) {
      instance.definition.renderer.update(instance.element, instance.props);
    } else {
      // 重新渲染
      this.rerenderComponent(instance);
    }
  }
  
  // 重新渲染组件
  private rerenderComponent(instance: ComponentInstance): void {
    if (!instance.element || !instance.element.parentElement) {
      return;
    }
    
    const container = instance.element.parentElement;
    container.removeChild(instance.element);
    this.renderComponent(instance, container);
  }
  
  // 创建默认元素
  private createDefaultElement(definition: ComponentDefinition, props: any): HTMLElement {
    const element = document.createElement('div');
    element.className = `component-${definition.type}`;
    element.textContent = props.text || definition.name;
    return element;
  }
  
  // 应用样式
  private applyStyles(styles: string, element: HTMLElement): void {
    const styleId = `component-styles-${Date.now()}`;
    let styleElement = document.getElementById(styleId) as HTMLStyleElement;
    
    if (!styleElement) {
      styleElement = document.createElement('style');
      styleElement.id = styleId;
      document.head.appendChild(styleElement);
    }
    
    styleElement.textContent = styles;
  }
  
  // 生成实例ID
  private generateInstanceId(): string {
    return `component-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }
  
  // 销毁组件实例
  destroyComponent(instance: ComponentInstance): void {
    if (instance.element && instance.element.parentElement) {
      instance.element.parentElement.removeChild(instance.element);
    }
    
    // 清理事件监听器
    if (instance.events) {
      Object.keys(instance.events).forEach(eventName => {
        if (instance.element) {
          instance.element.removeEventListener(eventName, instance.events[eventName]);
        }
      });
    }
    
    // 递归销毁子组件
    instance.children.forEach(child => {
      this.destroyComponent(child);
    });
    
    instance.children = [];
    instance.element = null;
  }
}

// 组件实例接口
interface ComponentInstance {
  id: string;
  componentId: string;
  definition: ComponentDefinition;
  props: any;
  element: HTMLElement | null;
  children: ComponentInstance[];
  parent: ComponentInstance | null;
  events: { [eventName: string]: Function };
  state: any;
}

5.3.3 完整使用示例

// 完整的组件系统使用示例
class LowCodeComponentDemo {
  private usageManager: ComponentUsageManager;
  private container: HTMLElement;
  
  constructor(container: HTMLElement) {
    this.container = container;
  }
  
  async initialize(): Promise<void> {
    // 初始化组件系统
    const { registry, loader } = await initializeComponentSystem();
    this.usageManager = new ComponentUsageManager(registry, loader);
    
    // 创建演示界面
    await this.createDemoInterface();
  }
  
  private async createDemoInterface(): Promise<void> {
    // 创建主容器
    const mainContainer = await this.usageManager.createComponentInstance(
      'container-component',
      {
        direction: 'vertical',
        gap: 20,
        padding: '20px',
        backgroundColor: '#f5f5f5'
      },
      this.container
    );
    
    // 创建标题
    const title = await this.usageManager.createComponentInstance(
      'text-component',
      {
        text: '低代码平台组件演示',
        fontSize: '24px',
        fontWeight: 'bold',
        color: '#333',
        textAlign: 'center'
      },
      mainContainer.element!
    );
    
    // 创建表单容器
    const formContainer = await this.usageManager.createComponentInstance(
      'container-component',
      {
        direction: 'vertical',
        gap: 16,
        padding: '20px',
        backgroundColor: 'white',
        border: '1px solid #e8e8e8',
        borderRadius: '8px'
      },
      mainContainer.element!
    );
    
    // 创建输入框
    const nameInput = await this.usageManager.createComponentInstance(
      'input-component',
      {
        placeholder: '请输入您的姓名',
        size: 'large',
        prefix: 'icon-user'
      },
      formContainer.element!
    );
    
    // 创建按钮容器
    const buttonContainer = await this.usageManager.createComponentInstance(
      'container-component',
      {
        direction: 'horizontal',
        gap: 12,
        justify: 'center'
      },
      formContainer.element!
    );
    
    // 创建提交按钮
    const submitButton = await this.usageManager.createComponentInstance(
      'button-component',
      {
        text: '提交',
        type: 'primary',
        size: 'large'
      },
      buttonContainer.element!
    );
    
    // 创建重置按钮
    const resetButton = await this.usageManager.createComponentInstance(
      'button-component',
      {
        text: '重置',
        type: 'secondary',
        size: 'large'
      },
      buttonContainer.element!
    );
    
    // 绑定事件
    this.bindEvents(nameInput, submitButton, resetButton);
  }
  
  private bindEvents(
    nameInput: ComponentInstance,
    submitButton: ComponentInstance,
    resetButton: ComponentInstance
  ): void {
    // 提交按钮事件
    if (submitButton.element) {
      submitButton.element.addEventListener('click', () => {
        const input = nameInput.element?.querySelector('input') as HTMLInputElement;
        const name = input?.value || '';
        
        if (name.trim()) {
          alert(`欢迎,${name}!`);
        } else {
          alert('请输入您的姓名');
        }
      });
    }
    
    // 重置按钮事件
    if (resetButton.element) {
      resetButton.element.addEventListener('click', () => {
        const input = nameInput.element?.querySelector('input') as HTMLInputElement;
        if (input) {
          input.value = '';
        }
      });
    }
  }
}

// 启动演示
const startDemo = async () => {
  const container = document.getElementById('app');
  if (container) {
    const demo = new LowCodeComponentDemo(container);
    await demo.initialize();
  }
};

// 页面加载完成后启动
document.addEventListener('DOMContentLoaded', startDemo);

5.4 小结

本章详细介绍了低代码平台的组件库系统,这是平台的核心功能模块之一。通过本章的学习,我们掌握了:

5.4.1 核心要点

  1. 组件库架构设计

    • 组件定义标准化
    • 组件注册与管理机制
    • 组件加载与渲染系统
    • 组件生命周期管理
  2. 组件实现技术

    • TypeScript 类型定义
    • 属性配置系统
    • 事件处理机制
    • 样式管理方案
    • 渲染器模式
  3. 组件分类与功能

    • 基础组件:文本、按钮、输入框
    • 布局组件:容器、栅格系统
    • 表单组件:各类输入控件
    • 展示组件:图表、表格等

5.4.2 技术特色

  1. 高度可扩展:支持动态注册和加载外部组件
  2. 类型安全:完整的 TypeScript 类型定义
  3. 性能优化:组件懒加载和按需渲染
  4. 开发友好:清晰的组件开发规范
  5. 功能完整:涵盖属性、事件、样式、插槽等

5.4.3 最佳实践

  1. 组件设计原则

    • 单一职责:每个组件专注特定功能
    • 可复用性:通过属性配置实现灵活性
    • 一致性:统一的设计语言和交互模式
  2. 性能优化策略

    • 组件懒加载减少初始加载时间
    • 虚拟滚动处理大量组件
    • 样式隔离避免冲突
  3. 开发规范

    • 完整的组件文档
    • 标准化的属性命名
    • 统一的事件处理模式

5.4.4 下一步学习

下一章我们将学习数据引擎与状态管理,了解如何: - 设计数据流架构 - 实现状态管理系统 - 处理数据绑定与同步 - 优化数据更新性能

组件库系统为低代码平台提供了丰富的UI构建能力,结合即将学习的数据引擎,将构成完整的应用开发基础设施。

  try {
    // 卸载旧版本
    await this.unregisterLibrary(libraryId);

    // 注册新版本
    await this.registerLibrary(newLibrary);

    // 触发更新事件
    this.eventBus.emit('library:updated', {
      oldLibrary: backup,
      newLibrary: newLibrary
    });
  } catch (error) {
    // 回滚到备份版本
    await this.registerLibrary(backup);
    throw error;
  }
} catch (error) {
  console.error(`Failed to update library "${library.name}":`, error);
  throw error;
}

}

// 获取组件库统计信息 getLibraryStats(): LibraryStats { const libraries = Array.from(this.libraries.values());

return {
  totalLibraries: libraries.length,
  totalComponents: libraries.reduce((sum, lib) => sum + lib.components.length, 0),
  librariesByType: this.groupLibrariesByType(libraries),
  componentsByCategory: this.groupComponentsByCategory(libraries),
  popularLibraries: this.getPopularLibraries(libraries)
};

}

private async validateLibrary(library: ComponentLibrary): Promise { // 验证基本信息 if (!library.id || !library.name || !library.version) { throw new Error(‘Library must have id, name, and version’); }

// 验证版本格式
if (!this.versionManager.isValidVersion(library.version)) {
  throw new Error(`Invalid version format: ${library.version}`);
}

// 检查是否已存在
if (this.libraries.has(library.id)) {
  throw new Error(`Library "${library.id}" already exists`);
}

// 验证组件
for (const component of library.components) {
  await this.validateComponent(component);
}

// 验证依赖
await this.validateDependencies(library.dependencies);

}

private async validateComponent(component: ComponentDefinition): Promise { // 验证组件定义 if (!component.id || !component.type || !component.name) { throw new Error(‘Component must have id, type, and name’); }

// 检查组件是否已存在
if (this.componentRegistry.getComponent(component.type)) {
  throw new Error(`Component type "${component.type}" already exists`);
}

// 验证属性定义
component.props.forEach(prop => {
  if (!prop.name || !prop.type) {
    throw new Error('Component property must have name and type');
  }
});

}

private async validateDependencies(dependencies: LibraryDependency[]): Promise { for (const dep of dependencies) { const library = this.libraries.get(dep.libraryId);

  if (dep.required && !library) {
    throw new Error(`Required dependency "${dep.libraryId}" not found`);
  }

  if (library && !this.versionManager.isVersionCompatible(library.version, dep.version)) {
    throw new Error(`Dependency version mismatch: ${dep.libraryId}@${dep.version}`);
  }
}

}

private checkLibraryDependencies(libraryId: string): void { const dependentLibraries = Array.from(this.libraries.values()) .filter(lib => lib.dependencies.some(dep => dep.libraryId === libraryId && dep.required ) );

if (dependentLibraries.length > 0) {
  const names = dependentLibraries.map(lib => lib.name).join(', ');
  throw new Error(`Cannot unregister library. Required by: ${names}`);
}

}

private async fetchLibraryVersion(libraryId: string, version: string): Promise { // 这里应该从组件库市场或仓库获取指定版本的组件库 // 为了示例,返回一个模拟的组件库 throw new Error(‘Library version fetching not implemented’); }

private groupLibrariesByType(libraries: ComponentLibrary[]): Record { return libraries.reduce((acc, lib) => { acc[lib.type] = (acc[lib.type] || 0) + 1; return acc; }, {} as Record); }

private groupComponentsByCategory(libraries: ComponentLibrary[]): Record { const components = libraries.flatMap(lib => lib.components); return components.reduce((acc, comp) => { acc[comp.category] = (acc[comp.category] || 0) + 1; return acc; }, {} as Record); }

private getPopularLibraries(libraries: ComponentLibrary[]): ComponentLibrary[] { return libraries .sort((a, b) => (b.downloadCount || 0) - (a.downloadCount || 0)) .slice(0, 10); }

private async initializeBuiltinLibraries(): Promise { // 注册内置组件库 const builtinLibrary: ComponentLibrary = { id: ‘builtin’, name: ‘内置组件库’, version: ‘1.0.0’, description: ‘平台内置的基础组件库’, author: ‘LowCode Platform’, type: ‘builtin’, tags: [‘builtin’, ‘basic’], components: [], // 将在后面定义 dependencies: [], assets: { css: [], js: [] }, downloadCount: 0, createdAt: new Date(), updatedAt: new Date() };

// 这里会添加内置组件
await this.registerLibrary(builtinLibrary);

} }

// 组件库接口定义 interface ComponentLibrary { id: string; name: string; version: string; description: string; author: string; type: ‘builtin’ | ‘official’ | ‘community’ | ‘private’; tags: string[]; components: ComponentDefinition[]; dependencies: LibraryDependency[]; assets: { css: string[]; js: string[]; }; downloadCount?: number; createdAt: Date; updatedAt: Date; }

interface LibraryDependency { libraryId: string; version: string; required: boolean; }

interface LibraryStats { totalLibraries: number; totalComponents: number; librariesByType: Record; componentsByCategory: Record; popularLibraries: ComponentLibrary[]; }


### 5.1.3 组件加载器

```typescript
// 组件加载器
class ComponentLoader {
  private loadedAssets: Set<string> = new Set();
  private loadingPromises: Map<string, Promise<void>> = new Map();
  private eventBus: EventBus;
  
  constructor(eventBus: EventBus) {
    this.eventBus = eventBus;
  }

  // 加载组件库
  async loadLibrary(library: ComponentLibrary): Promise<void> {
    try {
      // 加载依赖
      await this.loadDependencies(library.dependencies);
      
      // 加载CSS资源
      await this.loadCSSAssets(library.assets.css);
      
      // 加载JavaScript资源
      await this.loadJSAssets(library.assets.js);
      
      // 初始化组件
      await this.initializeComponents(library.components);
      
      console.log(`Library "${library.name}" loaded successfully`);
    } catch (error) {
      console.error(`Failed to load library "${library.name}":`, error);
      throw error;
    }
  }

  // 卸载组件库
  async unloadLibrary(library: ComponentLibrary): Promise<void> {
    try {
      // 清理组件
      await this.cleanupComponents(library.components);
      
      // 卸载资源
      await this.unloadAssets(library.assets);
      
      console.log(`Library "${library.name}" unloaded successfully`);
    } catch (error) {
      console.error(`Failed to unload library "${library.name}":`, error);
      throw error;
    }
  }

  // 懒加载组件
  async lazyLoadComponent(componentType: string): Promise<ComponentDefinition> {
    const cacheKey = `component:${componentType}`;
    
    // 检查是否已在加载中
    if (this.loadingPromises.has(cacheKey)) {
      await this.loadingPromises.get(cacheKey);
    }
    
    // 检查是否已加载
    const component = this.getLoadedComponent(componentType);
    if (component) {
      return component;
    }
    
    // 开始加载
    const loadingPromise = this.doLazyLoadComponent(componentType);
    this.loadingPromises.set(cacheKey, loadingPromise);
    
    try {
      await loadingPromise;
      return this.getLoadedComponent(componentType)!;
    } finally {
      this.loadingPromises.delete(cacheKey);
    }
  }

  private async loadDependencies(dependencies: LibraryDependency[]): Promise<void> {
    const requiredDeps = dependencies.filter(dep => dep.required);
    
    for (const dep of requiredDeps) {
      await this.loadDependency(dep);
    }
  }

  private async loadDependency(dependency: LibraryDependency): Promise<void> {
    // 这里应该加载依赖的组件库
    // 为了示例,只是记录日志
    console.log(`Loading dependency: ${dependency.libraryId}@${dependency.version}`);
  }

  private async loadCSSAssets(cssAssets: string[]): Promise<void> {
    const loadPromises = cssAssets.map(asset => this.loadCSSAsset(asset));
    await Promise.all(loadPromises);
  }

  private async loadCSSAsset(assetUrl: string): Promise<void> {
    if (this.loadedAssets.has(assetUrl)) {
      return;
    }
    
    return new Promise((resolve, reject) => {
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = assetUrl;
      
      link.onload = () => {
        this.loadedAssets.add(assetUrl);
        resolve();
      };
      
      link.onerror = () => {
        reject(new Error(`Failed to load CSS asset: ${assetUrl}`));
      };
      
      document.head.appendChild(link);
    });
  }

  private async loadJSAssets(jsAssets: string[]): Promise<void> {
    // 按顺序加载JavaScript资源
    for (const asset of jsAssets) {
      await this.loadJSAsset(asset);
    }
  }

  private async loadJSAsset(assetUrl: string): Promise<void> {
    if (this.loadedAssets.has(assetUrl)) {
      return;
    }
    
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = assetUrl;
      script.async = false; // 保持加载顺序
      
      script.onload = () => {
        this.loadedAssets.add(assetUrl);
        resolve();
      };
      
      script.onerror = () => {
        reject(new Error(`Failed to load JS asset: ${assetUrl}`));
      };
      
      document.head.appendChild(script);
    });
  }

  private async initializeComponents(components: ComponentDefinition[]): Promise<void> {
    for (const component of components) {
      await this.initializeComponent(component);
    }
  }

  private async initializeComponent(component: ComponentDefinition): Promise<void> {
    try {
      // 验证组件
      this.validateComponentDefinition(component);
      
      // 预编译组件模板
      if (component.template) {
        component.compiledTemplate = await this.compileTemplate(component.template);
      }
      
      // 初始化组件样式
      if (component.styles) {
        await this.initializeComponentStyles(component);
      }
      
      // 触发组件初始化事件
      this.eventBus.emit('component:initialized', component);
      
      console.log(`Component "${component.type}" initialized`);
    } catch (error) {
      console.error(`Failed to initialize component "${component.type}":`, error);
      throw error;
    }
  }

  private async cleanupComponents(components: ComponentDefinition[]): Promise<void> {
    for (const component of components) {
      await this.cleanupComponent(component);
    }
  }

  private async cleanupComponent(component: ComponentDefinition): Promise<void> {
    try {
      // 清理组件样式
      if (component.styles) {
        await this.cleanupComponentStyles(component);
      }
      
      // 清理编译缓存
      delete component.compiledTemplate;
      
      // 触发组件清理事件
      this.eventBus.emit('component:cleaned', component);
      
      console.log(`Component "${component.type}" cleaned up`);
    } catch (error) {
      console.error(`Failed to cleanup component "${component.type}":`, error);
    }
  }

  private async unloadAssets(assets: { css: string[]; js: string[] }): Promise<void> {
    // 卸载CSS资源
    assets.css.forEach(assetUrl => {
      const link = document.querySelector(`link[href="${assetUrl}"]`);
      if (link) {
        link.remove();
        this.loadedAssets.delete(assetUrl);
      }
    });
    
    // 卸载JavaScript资源
    assets.js.forEach(assetUrl => {
      const script = document.querySelector(`script[src="${assetUrl}"]`);
      if (script) {
        script.remove();
        this.loadedAssets.delete(assetUrl);
      }
    });
  }

  private async doLazyLoadComponent(componentType: string): Promise<void> {
    // 这里应该实现组件的懒加载逻辑
    // 例如从远程服务器加载组件定义
    console.log(`Lazy loading component: ${componentType}`);
  }

  private getLoadedComponent(componentType: string): ComponentDefinition | null {
    // 这里应该从组件注册表获取已加载的组件
    return null;
  }

  private validateComponentDefinition(component: ComponentDefinition): void {
    if (!component.id || !component.type || !component.name) {
      throw new Error('Component definition must have id, type, and name');
    }
  }

  private async compileTemplate(template: string): Promise<Function> {
    // 这里应该实现模板编译逻辑
    // 例如将模板编译为渲染函数
    return new Function('props', `return \`${template}\``);
  }

  private async initializeComponentStyles(component: ComponentDefinition): Promise<void> {
    if (!component.styles) return;
    
    const styleId = `component-style-${component.type}`;
    let styleElement = document.getElementById(styleId) as HTMLStyleElement;
    
    if (!styleElement) {
      styleElement = document.createElement('style');
      styleElement.id = styleId;
      document.head.appendChild(styleElement);
    }
    
    styleElement.textContent = component.styles;
  }

  private async cleanupComponentStyles(component: ComponentDefinition): Promise<void> {
    const styleId = `component-style-${component.type}`;
    const styleElement = document.getElementById(styleId);
    
    if (styleElement) {
      styleElement.remove();
    }
  }
}

5.2 内置组件实现

5.2.1 基础组件

// 文本组件
const TextComponent: ComponentDefinition = {
  id: 'text-component',
  name: '文本',
  type: 'text',
  category: 'basic',
  icon: 'icon-text',
  description: '用于显示文本内容的组件',
  version: '1.0.0',
  props: [
    {
      name: 'text',
      type: 'textarea',
      label: '文本内容',
      defaultValue: '文本内容',
      required: true,
      description: '要显示的文本内容'
    },
    {
      name: 'fontSize',
      type: 'number',
      label: '字体大小',
      defaultValue: 14,
      min: 8,
      max: 72,
      description: '文字的字体大小,单位为像素'
    },
    {
      name: 'color',
      type: 'color',
      label: '文字颜色',
      defaultValue: '#333333',
      description: '文字的颜色'
    },
    {
      name: 'fontWeight',
      type: 'select',
      label: '字体粗细',
      defaultValue: 'normal',
      options: [
        { label: '正常', value: 'normal' },
        { label: '粗体', value: 'bold' },
        { label: '细体', value: 'lighter' },
        { label: '特粗', value: 'bolder' }
      ],
      description: '文字的粗细程度'
    },
    {
      name: 'textAlign',
      type: 'select',
      label: '文字对齐',
      defaultValue: 'left',
      options: [
        { label: '左对齐', value: 'left' },
        { label: '居中', value: 'center' },
        { label: '右对齐', value: 'right' },
        { label: '两端对齐', value: 'justify' }
      ],
      description: '文字的对齐方式'
    },
    {
      name: 'lineHeight',
      type: 'number',
      label: '行高',
      defaultValue: 1.5,
      min: 1,
      max: 3,
      step: 0.1,
      description: '文字的行高倍数'
    }
  ],
  events: [
    {
      name: 'click',
      label: '点击事件',
      params: [
        { name: 'event', type: 'MouseEvent', description: '鼠标事件对象' },
        { name: 'component', type: 'ComponentInstance', description: '组件实例' }
      ],
      description: '当文本被点击时触发'
    },
    {
      name: 'mouseenter',
      label: '鼠标进入',
      params: [
        { name: 'event', type: 'MouseEvent', description: '鼠标事件对象' }
      ],
      description: '当鼠标进入文本区域时触发'
    },
    {
      name: 'mouseleave',
      label: '鼠标离开',
      params: [
        { name: 'event', type: 'MouseEvent', description: '鼠标事件对象' }
      ],
      description: '当鼠标离开文本区域时触发'
    }
  ],
  slots: [],
  defaultProps: {
    text: '文本内容',
    fontSize: 14,
    color: '#333333',
    fontWeight: 'normal',
    textAlign: 'left',
    lineHeight: 1.5
  },
  template: `
    <div 
      class="text-component" 
      style="
        font-size: {{fontSize}}px;
        color: {{color}};
        font-weight: {{fontWeight}};
        text-align: {{textAlign}};
        line-height: {{lineHeight}};
      "
      @click="handleClick"
      @mouseenter="handleMouseEnter"
      @mouseleave="handleMouseLeave"
    >
      {{text}}
    </div>
  `,
  styles: `
    .text-component {
      display: inline-block;
      word-wrap: break-word;
      word-break: break-all;
      white-space: pre-wrap;
      cursor: default;
      transition: all 0.2s ease;
    }
    
    .text-component:hover {
      opacity: 0.8;
    }
    
    .text-component.selectable {
      user-select: text;
    }
  `,
  preview: '/previews/text-component.png',
  renderer: {
    render: (props: any, events: any) => {
      const element = document.createElement('div');
      element.className = 'text-component';
      element.textContent = props.text || '';
      
      // 应用样式
      Object.assign(element.style, {
        fontSize: `${props.fontSize || 14}px`,
        color: props.color || '#333333',
        fontWeight: props.fontWeight || 'normal',
        textAlign: props.textAlign || 'left',
        lineHeight: props.lineHeight || 1.5
      });
      
      // 绑定事件
      if (events.click) {
        element.addEventListener('click', events.click);
      }
      if (events.mouseenter) {
        element.addEventListener('mouseenter', events.mouseenter);
      }
      if (events.mouseleave) {
        element.addEventListener('mouseleave', events.mouseleave);
      }
      
      return element;
    },
    
    update: (element: HTMLElement, props: any) => {
      element.textContent = props.text || '';
      
      Object.assign(element.style, {
        fontSize: `${props.fontSize || 14}px`,
        color: props.color || '#333333',
        fontWeight: props.fontWeight || 'normal',
        textAlign: props.textAlign || 'left',
        lineHeight: props.lineHeight || 1.5
      });
    }
  }
};

// 按钮组件
const ButtonComponent: ComponentDefinition = {
  id: 'button-component',
  name: '按钮',
  type: 'button',
  category: 'basic',
  icon: 'icon-button',
  description: '可点击的按钮组件',
  version: '1.0.0',
  props: [
    {
      name: 'text',
      type: 'string',
      label: '按钮文字',
      defaultValue: '按钮',
      required: true,
      description: '按钮上显示的文字'
    },
    {
      name: 'type',
      type: 'select',
      label: '按钮类型',
      defaultValue: 'primary',
      options: [
        { label: '主要按钮', value: 'primary' },
        { label: '次要按钮', value: 'secondary' },
        { label: '成功按钮', value: 'success' },
        { label: '警告按钮', value: 'warning' },
        { label: '危险按钮', value: 'danger' },
        { label: '信息按钮', value: 'info' },
        { label: '链接按钮', value: 'link' }
      ],
      description: '按钮的视觉类型'
    },
    {
      name: 'size',
      type: 'select',
      label: '按钮大小',
      defaultValue: 'medium',
      options: [
        { label: '小', value: 'small' },
        { label: '中', value: 'medium' },
        { label: '大', value: 'large' }
      ],
      description: '按钮的大小'
    },
    {
      name: 'disabled',
      type: 'boolean',
      label: '禁用状态',
      defaultValue: false,
      description: '是否禁用按钮'
    },
    {
      name: 'loading',
      type: 'boolean',
      label: '加载状态',
      defaultValue: false,
      description: '是否显示加载状态'
    },
    {
      name: 'icon',
      type: 'string',
      label: '图标',
      defaultValue: '',
      description: '按钮图标的类名'
    },
    {
      name: 'iconPosition',
      type: 'select',
      label: '图标位置',
      defaultValue: 'left',
      options: [
        { label: '左侧', value: 'left' },
        { label: '右侧', value: 'right' }
      ],
      description: '图标相对于文字的位置'
    }
  ],
  events: [
    {
      name: 'click',
      label: '点击事件',
      params: [
        { name: 'event', type: 'MouseEvent', description: '鼠标事件对象' },
        { name: 'component', type: 'ComponentInstance', description: '组件实例' }
      ],
      description: '当按钮被点击时触发'
    },
    {
      name: 'focus',
      label: '获得焦点',
      params: [
        { name: 'event', type: 'FocusEvent', description: '焦点事件对象' }
      ],
      description: '当按钮获得焦点时触发'
    },
    {
      name: 'blur',
      label: '失去焦点',
      params: [
        { name: 'event', type: 'FocusEvent', description: '焦点事件对象' }
      ],
      description: '当按钮失去焦点时触发'
    }
  ],
  slots: [],
  defaultProps: {
    text: '按钮',
    type: 'primary',
    size: 'medium',
    disabled: false,
    loading: false,
    icon: '',
    iconPosition: 'left'
  },
  template: `
    <button 
      class="btn btn-{{type}} btn-{{size}}" 
      :disabled="disabled || loading"
      @click="handleClick"
      @focus="handleFocus"
      @blur="handleBlur"
    >
      <span v-if="loading" class="btn-loading">
        <i class="icon-loading"></i>
      </span>
      <span v-else-if="icon && iconPosition === 'left'" class="btn-icon">
        <i :class="icon"></i>
      </span>
      <span class="btn-text">{{text}}</span>
      <span v-if="icon && iconPosition === 'right'" class="btn-icon">
        <i :class="icon"></i>
      </span>
    </button>
  `,
  styles: `
    .btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 4px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      font-family: inherit;
      font-weight: 500;
      text-decoration: none;
      transition: all 0.2s ease;
      outline: none;
      user-select: none;
    }
    
    .btn:focus {
      box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
    }
    
    .btn:disabled {
      cursor: not-allowed;
      opacity: 0.6;
    }
    
    /* 按钮大小 */
    .btn-small {
      padding: 4px 8px;
      font-size: 12px;
      min-height: 24px;
    }
    
    .btn-medium {
      padding: 8px 16px;
      font-size: 14px;
      min-height: 32px;
    }
    
    .btn-large {
      padding: 12px 24px;
      font-size: 16px;
      min-height: 40px;
    }
    
    /* 按钮类型 */
    .btn-primary {
      background-color: #1890ff;
      color: white;
    }
    
    .btn-primary:hover:not(:disabled) {
      background-color: #40a9ff;
    }
    
    .btn-secondary {
      background-color: #f5f5f5;
      color: #333;
      border: 1px solid #d9d9d9;
    }
    
    .btn-secondary:hover:not(:disabled) {
      background-color: #e6f7ff;
      border-color: #1890ff;
      color: #1890ff;
    }
    
    .btn-success {
      background-color: #52c41a;
      color: white;
    }
    
    .btn-success:hover:not(:disabled) {
      background-color: #73d13d;
    }
    
    .btn-warning {
      background-color: #faad14;
      color: white;
    }
    
    .btn-warning:hover:not(:disabled) {
      background-color: #ffc53d;
    }
    
    .btn-danger {
      background-color: #ff4d4f;
      color: white;
    }
    
    .btn-danger:hover:not(:disabled) {
      background-color: #ff7875;
    }
    
    .btn-info {
      background-color: #1890ff;
      color: white;
    }
    
    .btn-info:hover:not(:disabled) {
      background-color: #40a9ff;
    }
    
    .btn-link {
      background-color: transparent;
      color: #1890ff;
      border: none;
      padding: 0;
      min-height: auto;
    }
    
    .btn-link:hover:not(:disabled) {
      color: #40a9ff;
      text-decoration: underline;
    }
    
    /* 加载状态 */
    .btn-loading {
      display: inline-flex;
      align-items: center;
    }
    
    .icon-loading {
      animation: spin 1s linear infinite;
    }
    
    @keyframes spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
    
    /* 图标 */
    .btn-icon {
      display: inline-flex;
      align-items: center;
    }
  `,
  preview: '/previews/button-component.png',
  renderer: {
    render: (props: any, events: any) => {
      const button = document.createElement('button');
      button.className = `btn btn-${props.type || 'primary'} btn-${props.size || 'medium'}`;
      button.disabled = props.disabled || props.loading;
      
      // 构建按钮内容
      const content = [];
      
      if (props.loading) {
        content.push('<span class="btn-loading"><i class="icon-loading"></i></span>');
      } else if (props.icon && props.iconPosition === 'left') {
        content.push(`<span class="btn-icon"><i class="${props.icon}"></i></span>`);
      }
      
      content.push(`<span class="btn-text">${props.text || ''}</span>`);
      
      if (props.icon && props.iconPosition === 'right') {
        content.push(`<span class="btn-icon"><i class="${props.icon}"></i></span>`);
      }
      
      button.innerHTML = content.join('');
      
      // 绑定事件
      if (events.click) {
        button.addEventListener('click', events.click);
      }
      if (events.focus) {
        button.addEventListener('focus', events.focus);
      }
      if (events.blur) {
        button.addEventListener('blur', events.blur);
      }
      
      return button;
    },
    
    update: (element: HTMLButtonElement, props: any) => {
      element.className = `btn btn-${props.type || 'primary'} btn-${props.size || 'medium'}`;
      element.disabled = props.disabled || props.loading;
      
      // 更新按钮内容
      const content = [];
      
      if (props.loading) {
        content.push('<span class="btn-loading"><i class="icon-loading"></i></span>');
      } else if (props.icon && props.iconPosition === 'left') {
        content.push(`<span class="btn-icon"><i class="${props.icon}"></i></span>`);
      }
      
      content.push(`<span class="btn-text">${props.text || ''}</span>`);
      
      if (props.icon && props.iconPosition === 'right') {
        content.push(`<span class="btn-icon"><i class="${props.icon}"></i></span>`);
      }
      
      element.innerHTML = content.join('');
    }
  }
};

// 输入框组件
const InputComponent: ComponentDefinition = {
  id: 'input-component',
  name: '输入框',
  type: 'input',
  category: 'form',
  icon: 'icon-input',
  description: '用于用户输入文本的组件',
  version: '1.0.0',
  props: [
    {
      name: 'value',
      type: 'string',
      label: '输入值',
      defaultValue: '',
      description: '输入框的值'
    },
    {
      name: 'placeholder',
      type: 'string',
      label: '占位符',
      defaultValue: '请输入内容',
      description: '输入框的占位符文本'
    },
    {
      name: 'type',
      type: 'select',
      label: '输入类型',
      defaultValue: 'text',
      options: [
        { label: '文本', value: 'text' },
        { label: '密码', value: 'password' },
        { label: '邮箱', value: 'email' },
        { label: '数字', value: 'number' },
        { label: '电话', value: 'tel' },
        { label: '网址', value: 'url' },
        { label: '搜索', value: 'search' }
      ],
      description: '输入框的类型'
    },
    {
      name: 'size',
      type: 'select',
      label: '输入框大小',
      defaultValue: 'medium',
      options: [
        { label: '小', value: 'small' },
        { label: '中', value: 'medium' },
        { label: '大', value: 'large' }
      ],
      description: '输入框的大小'
    },
    {
      name: 'disabled',
      type: 'boolean',
      label: '禁用状态',
      defaultValue: false,
      description: '是否禁用输入框'
    },
    {
      name: 'readonly',
      type: 'boolean',
      label: '只读状态',
      defaultValue: false,
      description: '是否为只读状态'
    },
    {
      name: 'required',
      type: 'boolean',
      label: '必填项',
      defaultValue: false,
      description: '是否为必填项'
    },
    {
      name: 'maxLength',
      type: 'number',
      label: '最大长度',
      defaultValue: 0,
      min: 0,
      description: '输入内容的最大长度,0表示无限制'
    },
    {
      name: 'showClear',
      type: 'boolean',
      label: '显示清除按钮',
      defaultValue: false,
      description: '是否显示清除按钮'
    },
    {
      name: 'prefix',
      type: 'string',
      label: '前缀图标',
      defaultValue: '',
      description: '输入框前缀图标的类名'
    },
    {
      name: 'suffix',
      type: 'string',
      label: '后缀图标',
      defaultValue: '',
      description: '输入框后缀图标的类名'
    }
  ],
  events: [
    {
      name: 'input',
      label: '输入事件',
      params: [
        { name: 'value', type: 'string', description: '输入的值' },
        { name: 'event', type: 'InputEvent', description: '输入事件对象' }
      ],
      description: '当输入内容时触发'
    },
    {
      name: 'change',
      label: '变化事件',
      params: [
        { name: 'value', type: 'string', description: '输入的值' },
        { name: 'event', type: 'Event', description: '变化事件对象' }
      ],
      description: '当输入内容变化并失去焦点时触发'
    },
    {
      name: 'focus',
      label: '获得焦点',
      params: [
        { name: 'event', type: 'FocusEvent', description: '焦点事件对象' }
      ],
      description: '当输入框获得焦点时触发'
    },
    {
      name: 'blur',
      label: '失去焦点',
      params: [
        { name: 'event', type: 'FocusEvent', description: '焦点事件对象' }
      ],
      description: '当输入框失去焦点时触发'
    },
    {
      name: 'clear',
      label: '清除事件',
      params: [],
      description: '当点击清除按钮时触发'
    }
  ],
  slots: [],
  defaultProps: {
    value: '',
    placeholder: '请输入内容',
    type: 'text',
    size: 'medium',
    disabled: false,
    readonly: false,
    required: false,
    maxLength: 0,
    showClear: false,
    prefix: '',
    suffix: ''
  },
  template: `
    <div class="input-wrapper input-{{size}}" :class="{ 'input-disabled': disabled, 'input-focused': focused }">
      <span v-if="prefix" class="input-prefix">
        <i :class="prefix"></i>
      </span>
      <input 
        class="input-control"
        :type="type"
        :value="value"
        :placeholder="placeholder"
        :disabled="disabled"
        :readonly="readonly"
        :required="required"
        :maxlength="maxLength > 0 ? maxLength : null"
        @input="handleInput"
        @change="handleChange"
        @focus="handleFocus"
        @blur="handleBlur"
      >
      <span v-if="showClear && value" class="input-clear" @click="handleClear">
        <i class="icon-close"></i>
      </span>
      <span v-if="suffix" class="input-suffix">
        <i :class="suffix"></i>
      </span>
    </div>
  `,
  styles: `
    .input-wrapper {
      display: inline-flex;
      align-items: center;
      border: 1px solid #d9d9d9;
      border-radius: 4px;
      background-color: white;
      transition: all 0.2s ease;
      position: relative;
    }
    
    .input-wrapper:hover:not(.input-disabled) {
      border-color: #40a9ff;
    }
    
    .input-wrapper.input-focused {
      border-color: #1890ff;
      box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
    }
    
    .input-wrapper.input-disabled {
      background-color: #f5f5f5;
      cursor: not-allowed;
    }
    
    .input-control {
      flex: 1;
      border: none;
      outline: none;
      background: transparent;
      font-family: inherit;
      font-size: inherit;
      color: #333;
    }
    
    .input-control::placeholder {
      color: #bfbfbf;
    }
    
    .input-control:disabled {
      cursor: not-allowed;
      color: #bfbfbf;
    }
    
    /* 输入框大小 */
    .input-small {
      padding: 4px 8px;
      font-size: 12px;
      min-height: 24px;
    }
    
    .input-medium {
      padding: 8px 12px;
      font-size: 14px;
      min-height: 32px;
    }
    
    .input-large {
      padding: 12px 16px;
      font-size: 16px;
      min-height: 40px;
    }
    
    /* 前缀和后缀 */
    .input-prefix,
    .input-suffix {
      display: flex;
      align-items: center;
      color: #8c8c8c;
    }
    
    .input-prefix {
      margin-right: 8px;
    }
    
    .input-suffix {
      margin-left: 8px;
    }
    
    /* 清除按钮 */
    .input-clear {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      margin-left: 4px;
      cursor: pointer;
      color: #bfbfbf;
      border-radius: 50%;
      transition: all 0.2s ease;
    }
    
    .input-clear:hover {
      background-color: #f5f5f5;
      color: #8c8c8c;
    }
  `,
  preview: '/previews/input-component.png',
  renderer: {
    render: (props: any, events: any) => {
      const wrapper = document.createElement('div');
      wrapper.className = `input-wrapper input-${props.size || 'medium'}`;
      
      if (props.disabled) {
        wrapper.classList.add('input-disabled');
      }
      
      const content = [];
      
      // 前缀图标
      if (props.prefix) {
        content.push(`<span class="input-prefix"><i class="${props.prefix}"></i></span>`);
      }
      
      // 输入框
      const inputAttrs = [
        `type="${props.type || 'text'}"`,
        `value="${props.value || ''}"`,
        `placeholder="${props.placeholder || ''}"`,
        props.disabled ? 'disabled' : '',
        props.readonly ? 'readonly' : '',
        props.required ? 'required' : '',
        props.maxLength > 0 ? `maxlength="${props.maxLength}"` : ''
      ].filter(Boolean).join(' ');
      
      content.push(`<input class="input-control" ${inputAttrs}>`);
      
      // 清除按钮
      if (props.showClear && props.value) {
        content.push('<span class="input-clear"><i class="icon-close"></i></span>');
      }
      
      // 后缀图标
      if (props.suffix) {
        content.push(`<span class="input-suffix"><i class="${props.suffix}"></i></span>`);
      }
      
      wrapper.innerHTML = content.join('');
      
      // 绑定事件
      const input = wrapper.querySelector('.input-control') as HTMLInputElement;
      const clearBtn = wrapper.querySelector('.input-clear');
      
      if (input) {
        if (events.input) {
          input.addEventListener('input', (e) => {
            events.input((e.target as HTMLInputElement).value, e);
          });
        }
        if (events.change) {
          input.addEventListener('change', (e) => {
            events.change((e.target as HTMLInputElement).value, e);
          });
        }
        if (events.focus) {
          input.addEventListener('focus', (e) => {
            wrapper.classList.add('input-focused');
            events.focus(e);
          });
        }
        if (events.blur) {
          input.addEventListener('blur', (e) => {
            wrapper.classList.remove('input-focused');
            events.blur(e);
          });
        }
      }
      
      if (clearBtn && events.clear) {
        clearBtn.addEventListener('click', () => {
          if (input) {
            input.value = '';
            input.dispatchEvent(new Event('input', { bubbles: true }));
          }
          events.clear();
        });
      }
      
      return wrapper;
    },
    
    update: (element: HTMLElement, props: any) => {
      const input = element.querySelector('.input-control') as HTMLInputElement;
      if (input) {
        input.value = props.value || '';
        input.placeholder = props.placeholder || '';
        input.disabled = props.disabled;
        input.readOnly = props.readonly;
        input.required = props.required;
        
        if (props.maxLength > 0) {
          input.maxLength = props.maxLength;
        } else {
          input.removeAttribute('maxlength');
        }
      }
      
      // 更新样式类
      element.className = `input-wrapper input-${props.size || 'medium'}`;
      if (props.disabled) {
        element.classList.add('input-disabled');
      }
    }
  }
};

5.2.2 布局组件

// 容器组件
const ContainerComponent: ComponentDefinition = {
  id: 'container-component',
  name: '容器',
  type: 'container',
  category: 'layout',
  icon: 'icon-container',
  description: '用于包含其他组件的容器',
  version: '1.0.0',
  props: [
    {
      name: 'direction',
      type: 'select',
      label: '排列方向',
      defaultValue: 'vertical',
      options: [
        { label: '垂直', value: 'vertical' },
        { label: '水平', value: 'horizontal' }
      ],
      description: '子组件的排列方向'
    },
    {
      name: 'justify',
      type: 'select',
      label: '主轴对齐',
      defaultValue: 'flex-start',
      options: [
        { label: '起始对齐', value: 'flex-start' },
        { label: '居中对齐', value: 'center' },
        { label: '末尾对齐', value: 'flex-end' },
        { label: '两端对齐', value: 'space-between' },
        { label: '环绕对齐', value: 'space-around' },
        { label: '均匀分布', value: 'space-evenly' }
      ],
      description: '主轴上的对齐方式'
    },
    {
      name: 'align',
      type: 'select',
      label: '交叉轴对齐',
      defaultValue: 'stretch',
      options: [
        { label: '拉伸', value: 'stretch' },
        { label: '起始对齐', value: 'flex-start' },
        { label: '居中对齐', value: 'center' },
        { label: '末尾对齐', value: 'flex-end' },
        { label: '基线对齐', value: 'baseline' }
      ],
      description: '交叉轴上的对齐方式'
    },
    {
      name: 'gap',
      type: 'number',
      label: '间距',
      defaultValue: 0,
      min: 0,
      description: '子组件之间的间距,单位为像素'
    },
    {
      name: 'wrap',
      type: 'boolean',
      label: '允许换行',
      defaultValue: false,
      description: '是否允许子组件换行'
    },
    {
      name: 'padding',
      type: 'string',
      label: '内边距',
      defaultValue: '0',
      description: '容器的内边距'
    },
    {
      name: 'backgroundColor',
      type: 'color',
      label: '背景色',
      defaultValue: 'transparent',
      description: '容器的背景色'
    },
    {
      name: 'border',
      type: 'string',
      label: '边框',
      defaultValue: 'none',
      description: '容器的边框样式'
    },
    {
      name: 'borderRadius',
      type: 'string',
      label: '圆角',
      defaultValue: '0',
      description: '容器的圆角大小'
    }
  ],
  events: [
    {
      name: 'click',
      label: '点击事件',
      params: [
        { name: 'event', type: 'MouseEvent', description: '鼠标事件对象' }
      ],
      description: '当容器被点击时触发'
    }
  ],
  slots: [
    {
      name: 'default',
      label: '默认插槽',
      description: '容器的主要内容区域'
    }
  ],
  defaultProps: {
    direction: 'vertical',
    justify: 'flex-start',
    align: 'stretch',
    gap: 0,
    wrap: false,
    padding: '0',
    backgroundColor: 'transparent',
    border: 'none',
    borderRadius: '0'
  },
  template: `
    <div 
      class="container-component"
      :style="{
        flexDirection: direction === 'horizontal' ? 'row' : 'column',
        justifyContent: justify,
        alignItems: align,
        gap: gap + 'px',
        flexWrap: wrap ? 'wrap' : 'nowrap',
        padding: padding,
        backgroundColor: backgroundColor,
        border: border,
        borderRadius: borderRadius
      }"
      @click="handleClick"
    >
      <slot name="default"></slot>
    </div>
  `,
  styles: `
    .container-component {
      display: flex;
      min-height: 50px;
      min-width: 100px;
      position: relative;
    }
    
    .container-component.container-empty {
      border: 2px dashed #d9d9d9;
      background-color: #fafafa;
    }
    
    .container-component.container-empty::after {
      content: '拖拽组件到此处';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      color: #bfbfbf;
      font-size: 14px;
      pointer-events: none;
    }
    
    .container-component.drop-target {
      border: 2px dashed #1890ff;
      background-color: rgba(24, 144, 255, 0.05);
    }
  `,
  preview: '/previews/container-component.png',
  renderer: {
    render: (props: any, events: any) => {
      const container = document.createElement('div');
      container.className = 'container-component';
      
      // 应用样式
      Object.assign(container.style, {
        flexDirection: props.direction === 'horizontal' ? 'row' : 'column',
        justifyContent: props.justify || 'flex-start',
        alignItems: props.align || 'stretch',
        gap: `${props.gap || 0}px`,
        flexWrap: props.wrap ? 'wrap' : 'nowrap',
        padding: props.padding || '0',
        backgroundColor: props.backgroundColor || 'transparent',
        border: props.border || 'none',
        borderRadius: props.borderRadius || '0'
      });
      
      // 绑定事件
      if (events.click) {
        container.addEventListener('click', events.click);
      }
      
      return container;
    },
    
    update: (element: HTMLElement, props: any) => {
      Object.assign(element.style, {
        flexDirection: props.direction === 'horizontal' ? 'row' : 'column',
        justifyContent: props.justify || 'flex-start',
        alignItems: props.align || 'stretch',
        gap: `${props.gap || 0}px`,
        flexWrap: props.wrap ? 'wrap' : 'nowrap',
        padding: props.padding || '0',
        backgroundColor: props.backgroundColor || 'transparent',
        border: props.border || 'none',
        borderRadius: props.borderRadius || '0'
      });
    }
  }
};

// 栅格组件
const GridComponent: ComponentDefinition = {
  id: 'grid-component',
  name: '栅格',
  type: 'grid',
  category: 'layout',
  icon: 'icon-grid',
  description: '基于CSS Grid的栅格布局组件',
  version: '1.0.0',
  props: [
    {
      name: 'columns',
      type: 'number',
      label: '列数',
      defaultValue: 12,
      min: 1,
      max: 24,
      description: '栅格的列数'
    },
    {
      name: 'rows',
      type: 'number',
      label: '行数',
      defaultValue: 1,
      min: 1,
      description: '栅格的行数'
    },
    {
      name: 'columnGap',
      type: 'number',
      label: '列间距',
      defaultValue: 16,
      min: 0,
      description: '列之间的间距,单位为像素'
    },
    {
      name: 'rowGap',
      type: 'number',
      label: '行间距',
      defaultValue: 16,
      min: 0,
      description: '行之间的间距,单位为像素'
    },
    {
      name: 'autoRows',
      type: 'string',
      label: '自动行高',
      defaultValue: 'auto',
      description: '自动生成行的高度'
    },
    {
      name: 'justifyItems',
      type: 'select',
      label: '项目水平对齐',
      defaultValue: 'stretch',
      options: [
        { label: '拉伸', value: 'stretch' },
        { label: '起始对齐', value: 'start' },
        { label: '居中对齐', value: 'center' },
        { label: '末尾对齐', value: 'end' }
      ],
      description: '栅格项目的水平对齐方式'
    },
    {
      name: 'alignItems',
      type: 'select',
      label: '项目垂直对齐',
      defaultValue: 'stretch',
      options: [
        { label: '拉伸', value: 'stretch' },
        { label: '起始对齐', value: 'start' },
        { label: '居中对齐', value: 'center' },
        { label: '末尾对齐', value: 'end' }
      ],
      description: '栅格项目的垂直对齐方式'
    }
  ],
  events: [
    {
      name: 'click',
      label: '点击事件',
      params: [
        { name: 'event', type: 'MouseEvent', description: '鼠标事件对象' }
      ],
      description: '当栅格被点击时触发'
    }
  ],
  slots: [
    {
      name: 'default',
      label: '默认插槽',
      description: '栅格的内容区域'
    }
  ],
  defaultProps: {
    columns: 12,
    rows: 1,
    columnGap: 16,
    rowGap: 16,
    autoRows: 'auto',
    justifyItems: 'stretch',
    alignItems: 'stretch'
  },
  template: `
    <div 
      class="grid-component"
      :style="{
        gridTemplateColumns: 'repeat(' + columns + ', 1fr)',
        gridTemplateRows: rows > 1 ? 'repeat(' + rows + ', 1fr)' : 'none',
        gridAutoRows: autoRows,
        columnGap: columnGap + 'px',
        rowGap: rowGap + 'px',
        justifyItems: justifyItems,
        alignItems: alignItems
      }"
      @click="handleClick"
    >
      <slot name="default"></slot>
    </div>
  `,
  styles: `
    .grid-component {
      display: grid;
      min-height: 100px;
      width: 100%;
    }
    
    .grid-component.grid-empty {
      border: 2px dashed #d9d9d9;
      background-color: #fafafa;
      position: relative;
    }
    
    .grid-component.grid-empty::after {
      content: '拖拽组件到栅格中';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      color: #bfbfbf;
      font-size: 14px;
      pointer-events: none;
    }
    
    .grid-component.drop-target {
      border: 2px dashed #1890ff;
      background-color: rgba(24, 144, 255, 0.05);
    }
  `,
  preview: '/previews/grid-component.png',
  renderer: {
    render: (props: any, events: any) => {
      const grid = document.createElement('div');
      grid.className = 'grid-component';
      
      // 应用样式
      Object.assign(grid.style, {
        gridTemplateColumns: `repeat(${props.columns || 12}, 1fr)`,
        gridTemplateRows: props.rows > 1 ? `repeat(${props.rows}, 1fr)` : 'none',
        gridAutoRows: props.autoRows || 'auto',
        columnGap: `${props.columnGap || 16}px`,
        rowGap: `${props.rowGap || 16}px`,
        justifyItems: props.justifyItems || 'stretch',
        alignItems: props.alignItems || 'stretch'
      });
      
      // 绑定事件
      if (events.click) {
        grid.addEventListener('click', events.click);
      }
      
      return grid;
    },
    
    update: (element: HTMLElement, props: any) => {
      Object.assign(element.style, {
        gridTemplateColumns: `repeat(${props.columns || 12}, 1fr)`,
        gridTemplateRows: props.rows > 1 ? `repeat(${props.rows}, 1fr)` : 'none',
        gridAutoRows: props.autoRows || 'auto',
        columnGap: `${props.columnGap || 16}px`,
        rowGap: `${props.rowGap || 16}px`,
        justifyItems: props.justifyItems || 'stretch',
        alignItems: props.alignItems || 'stretch'
      });
    }
  }
};