## Vue 3 Composition API Research - Modular Architecture Best Practices ### 研究日期: 2026-02-03 --- ## 1. 官方 Vue 3 组件组织原则 ### 1.1 Composables 用于代码组织 来源: Vue 官方文档 - https://vuejs.org/guide/reusability/composables **核心原则:** - Composables 不仅用于复用,也用于**代码组织** - 当组件变得过于复杂时,应该将逻辑按**关注点分离**提取到更小的函数中 - 可以将提取的 composables 视为**组件级别的服务**,它们可以相互通信 **官方示例模式:** ```vue ``` **关键洞察:** - Composables 应返回**普通对象**包含多个 refs,保持响应式 - 避免返回 reactive 对象,因为解构会失去响应性 - Composables 可以接收其他 composables 的返回值作为参数 --- ## 2. 代码分割与懒加载 ### 2.1 defineAsyncComponent 用于模块懒加载 来源: Vue 官方文档 - https://github.com/vuejs/docs/blob/main/src/guide/best-practices/performance.md **适用场景:** - 将大型组件树分割成独立的 chunks - 仅在组件渲染时才加载,改善初始加载时间 ```js import { defineAsyncComponent } from 'vue' // Foo.vue 及其依赖被单独打包成一个 chunk // 只有在组件被渲染时才会按需获取 const Foo = defineAsyncComponent(() => import('./Foo.vue')) ``` ### 2.2 动态导入用于 JS 代码分割 ```js // lazy.js 及其依赖会被分割成单独的 chunk // 只在 loadLazy() 被调用时才加载 function loadLazy() { return import('./lazy.js') } ``` --- ## 3. 真实世界的模块化架构模式 ### 3.1 Dashboard 模块化架构 - 成功案例 **案例 1: Soybean Admin (MIT License)** 来源: https://github.com/soybeanjs/soybean-admin/blob/main/src/views/home/index.vue ```vue ``` **架构特点:** - Index.vue 作为**容器组件**,只负责布局和响应式计算 - 每个 modules/*.vue 是**独立的功能模块** - 模块命名清晰: header-banner, card-data, line-chart 等 - 使用 Pinia store 进行状态共享 **案例 2: Art Design Pro (MIT License)** 来源: https://github.com/Daymychen/art-design-pro/blob/main/src/views/dashboard/ecommerce/index.vue ```vue ``` **架构特点:** - 电商 dashboard 包含 13 个独立模块 - 每个模块代表一个业务功能卡片 - Index.vue **不传递数据**,模块自治 --- ## 4. 模块间通信模式 ### 4.1 defineEmits 用于子到父通信 来源: Vue 核心仓库 - https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiSetupHelpers.ts **TypeScript 类型声明模式:** ```ts const emit = defineEmits<{ 'update:modelValue': [value: string]; 'change': [event: Event]; 'custom-event': [payload: CustomPayload]; }>(); ``` **Runtime 声明模式:** ```js const emit = defineEmits(['change', 'update']) ``` ### 4.2 Props 模式 - 数据传递 vs 自取数据 **案例研究: Halo CMS (GPL-3.0)** 来源: https://github.com/halo-dev/halo/blob/main/ui/console-src/modules/system/users/components/GrantPermissionModal.vue ```vue ``` **模式总结:** - **Props 传递身份标识** (如 user ID),而非完整数据 - **模块自己获取详细数据** (通过 composables) - 这样保持模块的**高内聚低耦合** --- ## 5. 何时模块应该自取数据 vs 接收 Props ### 5.1 自取数据的场景 - 模块是**独立的业务单元**(如日历、统计卡片) - 数据获取逻辑属于模块内部关注点 - 模块需要**定期刷新**或**重新加载**数据 - 多个平行模块各自管理自己的状态 **示例:** ```vue ``` ### 5.2 接收 Props 的场景 - 模块是**展示组件**(Presentational Component) - 父组件需要**协调多个子组件**的数据 - 数据来源于**全局状态管理**(如 Pinia store) - 需要在父组件层面做**数据聚合或转换** **示例:** ```vue ``` --- ## 6. TypeScript vs JavaScript 在 Vue 3 项目中 ### 6.1 EmailBill 项目的选择 **当前状况:** - ESLint 配置中禁用了 TypeScript 规则 - 使用 `