Vue 3 组件化架构

技术基础:Vue 3 Composition API + <script setup>


一、理念

1.1 设计目标

目标 说明
逻辑复用 相同逻辑只写一次
清晰分层 各层职责明确,易于维护
适度拆分 不为了拆分而拆分,简单文件保持单文件

1.2 核心观点

  • ❌ 不能为了拆分而拆分,几十行的文件不需要拆分
  • ❌ 文件过多管理麻烦,不应刻意拆分
  • ✅ 多处复用才有必要提取
  • ✅ 逻辑复杂才需要拆分

二、规则

2.1 核心数值

原则 数值 说明
页面拆分 > 300 行 才考虑拆分子组件
Composable 拆分 > 150 行 才考虑拆分
复用提取 多处复用 才有必要提取

2.2 组件三层架构

层次 存放位置 复用范围
L1 通用 UI packages/ui/ 跨项目复用
L2 业务组件 app/xxx/src/components/ 仅当前项目
L3 页面组件 app/xxx/src/views/xxx/components/ 仅当前页面

2.3 拆分时机

场景 动作
某组件多处使用 移到 components/(L2)
L2 组件只在某页面使用且 < 300 行 移到 views/xxx/components/(L3)
L3 组件被另一页面复用 移到 components/(L2)

三、补充详解

3.1 各层职责

L1:packages/ui(通用 UI)

基础 UI 封装,跨项目复用。如:jm-crud、jm-panel、jm-layout、jm-table

特点:无业务逻辑,纯 UI 封装,跨项目复用

L2:components/(业务组件)

本项目内复用,按业务模块分类。如:UserForm、UserTable、SearchBar

特点:有业务逻辑,本项目内复用,按业务模块分类

L3:views/xxx/components/(页面私有)

仅当前页面使用,不复用。如:LoginHeader、UserDetail

特点:仅当前页面使用,不复用


3.2 目录结构

monorepo_front/
├── packages/                      # L1:通用 UI 组件(跨项目)
│   └── ui/
│       ├── components/
│       │   ├── crud/            # jm-crud
│       │   ├── panel/           # jm-panel
│       │   └── table/           # jm-table
│       └── index.ts
│
└── app/
    └── volunteer/
        └── src/
            ├── components/        # L2:本项目通用业务组件
            │   ├── user/
            │   │   ├── UserForm.vue
            │   │   └── UserTable.vue
            │   └── common/
            │       └── SearchBar.vue
            │
            ├── views/            # 页面
            │   └── auth/
            │       ├── LoginPage.vue
            │       └── components/  # L3:页面私有组件
            │           └── LoginHeader.vue
            │
            ├── composables/      # 逻辑复用
            ├── stores/           # 全局状态
            └── api/              # API 调用

3.3 Composable 使用

类型 复用方式 存放位置
Composable 逻辑复用,无 UI composables/
L2/L3 组件 UI + 逻辑复用 components/ / views/xxx/components/

说明:Composable 负责逻辑,组件负责 UI + 逻辑组合


3.4 Smart/Dumb 组件模式

类型 别名 职责 有无业务逻辑
Smart Container / 业务组件 数据获取、API 调用、状态处理 ✅ 有
Dumb Presentational / 展示组件 纯 UI 展示,只通过 props/emits ❌ 无

Vue 3 实践

UserListPage.vue(Smart 业务组件)
    ↓ props
    UserTable.vue(Dumb 展示组件)
    ↓ emits
    UserListPage.vue(处理事件)

3.5 现有目录对照

现有目录 新目录 说明
hooks/ composables/ 命名统一为 Vue 3 习惯
api/ api/ 保持不变
stores/ stores/ 保持不变
components/ L2: components/ / L3: views/xxx/components/ 按层级分类

四、核心原则

  1. 不为了拆分而拆分 – 简单文件保持单文件
  2. 多处复用才提取 – 只有被多处使用时才移到 components/
  3. 逻辑复杂才拆 – 超过行数限制才考虑拆分

📝 详细规范请参考源文档