一、组件类型分类与特性

1. 全局组件

定义:通过 app.component(Vue3)或 Vue.component(Vue2)注册,可在任意位置使用。
核心特性

  • 适用场景:高频复用的基础 UI 组件(如按钮、图标、加载动画)。

  • 批量注册(Vue3):

    // main.js(Vue3)
    const app = createApp(App);
    // 自动注册 src/components/global 目录下所有组件(需配合 Vite 的 import.meta.glob)
    const globalComponents = import.meta.glob('./components/global/*.vue', { eager: false }); // 默认异步加载
    Object.entries(globalComponents).forEach(([path, component]) => {
      const name = path.split('/').pop()?.replace('.vue', '');
      if (name) {
        app.component(`G${name}`, defineAsyncComponent(component)); // 异步加载
      }
    });
    
  • 注意事项

    • 全局组件注册后会被包含在最终打包产物中,即使未使用也会占用体积,因此不宜过多注册(建议不超过 10 个基础组件)。
    • Vue3 中需通过 app.config.globalProperties 扩展类型提示(TypeScript),但更推荐使用 Provide/Inject插件机制 替代全局属性。
2. 局部组件

定义:在组件内部通过 components 选项或 <script setup> 自动注册,仅限当前组件使用。
核心特性

  • 适用场景:业务模块内复用组件(如订单模块的 OrderListOrderItem)。
  • Vue3 简化注册<script setup>):
    <script setup>
    import LocalCard from './LocalCard.vue'; // 导入即自动注册
    </script>
    
    <template>
      <LocalCard title="局部组件" /> <!-- 直接使用 -->
    </template>
    
  • 注意事项
    • 作用域隔离,父组件无法直接访问子组件内部状态(需通过 props/events 通信)。
3. 动态组件

定义:通过 <component :is="currentComponent"> 动态切换组件。
核心特性

  • 适用场景:选项卡、步骤条、条件渲染(需结合 keep-alive 缓存)。
  • 缓存控制
    <keep-alive include="TabA,TabB" :max="3">
      <component :is="currentTab" />
    </keep-alive>
    
  • 生命周期
    • 缓存组件触发 activated/deactivated
    • 非缓存组件正常触发 mounted/unmounted
4. 泛型组件

定义:通过 TypeScript 泛型实现类型复用(Vue3 + TS)。
核心特性

  • 适用场景:通用组件(如表格、列表、表单)。
  • 规范写法<script setup>):
    <!-- GenericList.vue -->
    <template>
      <ul>
        <li v-for="item in items" :key="item[labelKey]">
          {{ item[labelKey] }}
        </li>
      </ul>
    </template>
    
    <script setup lang="ts" generic="T extends Record<string, any>"> <!-- 明确泛型约束 -->
    const props = defineProps<{
      items: T[];
      labelKey: keyof T; // 确保 labelKey 是 T 的属性
    }>();
    </script>
    
  • 父组件使用
    <GenericList :items="users" labelKey="name" />
    
5. 递归组件

定义:组件内部调用自身,需设置 name 和终止条件。
核心特性

  • 适用场景:树形结构、嵌套评论、JSON 可视化。
  • 显式命名(Vue3):
    <script>
    export default { name: 'TreeNode' }; // 必须设置 name(Options API)
    </script>
    
    <script setup lang="ts">
    // Composition API 中可通过文件名隐式推断 name(需配合 Volar 插件)
    // 或显式定义:
    defineOptions({ name: 'TreeNode' }); // Vue 3.3+ 支持
    </script>
    
  • 深度控制
    <template>
      <div v-if="depth < 10"> <!-- 限制最大深度 -->
        {{ node.name }}
        <TreeNode 
          v-for="child in node.children" 
          :node="child" 
          :depth="depth + 1" 
        />
      </div>
    </template>
    
6. 异步组件

定义:按需加载组件,优化首屏性能。
核心特性

  • 适用场景:非首屏组件、路由懒加载。
  • Vue3 简化写法
    <script setup>
    const AsyncModal = defineAsyncComponent(() => import('./Modal.vue')); // 推荐写法
    </script>
    
  • 加载状态处理
    const AsyncComponent = defineAsyncComponent({
      loader: () => import('./Component.vue'),
      loadingComponent: LoadingSpinner,
      errorComponent: ErrorFallback,
      delay: 200, // 延迟显示加载组件(避免闪烁)
      timeout: 3000, // 超时时间
      suspensible: false // 是否在 Suspense 边界内使用(默认 false)
    });
    

二、总结

类型 适用场景 关键注意事项 Vue2 vs Vue3 差异
全局组件 基础 UI 组件(按钮、图标) 避免过度注册,控制打包体积;推荐使用插件机制替代全局属性 Vue2 用 Vue.component,Vue3 用 app.component
局部组件 业务模块内复用(如订单组件) 作用域隔离,<script setup> 自动注册 Vue3 支持更简洁的自动注册语法
动态组件 选项卡、步骤条、条件渲染 结合 keep-alive 优化性能,max 支持动态绑定 一致,Vue3 优化了缓存逻辑
泛型组件 通用组件(表格、列表) 依赖 TypeScript,需显式声明泛型约束 Vue3 支持 <script setup> 泛型语法
递归组件 树形结构、嵌套评论 必须设置 name,控制递归深度;支持 defineOptions Vue3 需单独声明 name(Options API)
异步组件 大型组件、路由懒加载 需处理加载/失败状态,推荐 defineAsyncComponent Vue3 新增 defineAsyncComponent,支持 Suspense

更多推荐