vue的组件拆分有什么心得

Vue 组件拆分实战心得(Vue2/Vue3 通用,从入门到企业规范)

一、先记住核心拆分原则(所有拆分的底层依据)

1. 单一职责原则(最重要)

一个组件只做一件事:
  • 只负责展示 → 展示组件
  • 只负责表单录入 → 表单组件
  • 只负责表格列表 → 表格组件
     
    禁止一个页面几千行代码,列表、搜索、新增弹窗、详情、编辑全写在一个 .vue 里。
反例:
 
UserList.vue 包含:搜索栏、表格、分页、新增弹窗、编辑弹窗、详情弹窗、批量删除、导入导出、各种状态渲染。
 
正例:把弹窗、搜索、表格单独抽离。

2. 可复用原则:多处用到的必须抽公共组件

只要页面出现≥2 次相同 UI / 逻辑,立刻抽成公共组件:
  • 通用:分页、上传、弹窗、卡片、状态标签、搜索栏、按钮组、权限按钮
  • 业务:订单状态卡片、商品信息卡片、用户选择器、文件预览弹窗

3. 复杂度阈值原则(行数红线)

  • 单个组件建议:≤300 行,最多不超过 500 行
  • 超过直接拆分:模板太长、方法几十行、大量 v-if、复杂计算属性,优先拆子组件
  • 弹窗、抽屉、复杂表单,一律单独新建组件,不要写在页面内部

4. 分层原则:页面按「页面容器 → 业务子组件 → 公共基础组件」三层拆分

  1. 页面级(views):只做统筹
     
    负责:请求接口、管理全局状态、父子传参、控制弹窗显隐、分发数据,不写复杂 DOM、不封装复杂工具方法。
  2. 业务组件级(components/business):当前业务内复用
     
    用户表格、角色表单、筛选区域、详情卡片,只在当前模块复用。
  3. 公共基础组件(components/common):全局任意页面可复用
     
    通用弹窗、分页、图片预览、上传、空状态、权限按钮等。

5. 数据驱动原则:按「数据维度」拆分,不是按视觉位置拆分

不要凭页面上下左右拆分,要按数据归属拆分:
  • 同一批接口返回的数据渲染的区域 → 可以放一个组件
  • 依赖不同接口、不同状态控制的模块 → 必须拆分
     
    例:
     
    列表页:搜索区(筛选参数)、表格区(列表数据)、操作弹窗(表单数据),三份独立数据源,天然拆 3 个组件。

二、四种经典组件拆分场景 + 最佳实践

场景 1:列表页(后台管理系统最常见)

原始大页面:搜索栏 + 表格 + 分页 + 新增 / 编辑弹窗 + 详情弹窗
 
推荐拆分结构:
plaintext
 
 
views/user/
├─ index.vue          # 父页面(控制器)
├─ components/
   ├─ UserSearch.vue  # 搜索筛选组件
   ├─ UserTable.vue   # 表格+分页组件
   ├─ UserForm.vue    # 新增、编辑共用表单弹窗
   └─ UserDetail.vue  # 详情抽屉/弹窗
 

父子职责划分(黄金分工)

  1. 父页面 index.vue
  • 定义查询参数、列表数组、弹窗显隐标识
  • 封装列表请求、新增 / 编辑 / 删除接口调用
  • 通过 props 向下传:查询条件、表格数据、弹窗打开状态
  • 通过自定义事件 $emit 接收子组件触发的搜索、新增、保存、删除等动作
  1. 子组件只做两件事:UI 渲染 + 事件向上派发
  • 不直接发请求,不操作 Vuex 全局状态
  • 只通过 props 接收数据,通过事件告诉父页面 “我要做什么操作”
核心好处:子组件高度纯净、可复用、方便单元测试、后期改 UI 只动子组件,不会污染父页面逻辑。

场景 2:复杂表单页(多步骤、多区块、超长表单)

比如:订单提交页,包含基础信息、收件地址、商品清单、发票信息、备注。
 
拆分思路:按业务区块拆分,共用父页面统一收集表单数据。
plaintext
 
 
views/order/create/
├─ index.vue
└─ components/
   ├─ BaseInfo.vue
   ├─ AddressSelect.vue
   ├─ GoodsList.vue
   └─ InvoiceForm.vue
 
传参方案:父页面维护一个大表单对象,通过 v-model / props + emit 双向同步各子组件字段,最终统一提交。

场景 3:弹窗 / 抽屉组件(高频踩坑点)

❌ 错误:弹窗直接写在父页面 template 里,v-if 控制显隐,代码堆积。
 
✅ 正确:弹窗单独抽组件,父页面通过布尔值控制引入、打开关闭。
 
优点:
  1. 弹窗关闭销毁组件,避免上次表单数据缓存污染
  2. 表单校验、字段规则封装在弹窗内部,父页面更清爽
  3. 同一个弹窗可以在多个按钮处复用

场景 4:全局通用 UI 组件

多处页面用到:空数据、分页、文件上传、图片预览、通用表格、封装 el-dialog。
 
统一放在 src/components/common,全局注册或按需引入,带默认属性、支持自定义插槽,统一 UI 规范。

三、组件通信选型(拆分后配套规范,避免乱传参)

  1. 父子组件:优先 props向下传 + $emit向上抛事件
     
    禁止子组件直接修改 props、子组件操作父页面变量。
  2. 跨层级多层组件:
    • Vue2:简单场景用 $attrs/$listeners;复杂全局状态(登录、权限、字典)放 Vuex
    • 不要多层父子层层透传参数(prop 逐级穿透),尽量抽全局状态。
  3. 兄弟组件:通过父页面中转,或者用 Vuex。
  4. 全局弹窗、全局提示类组件:挂载 Vue 原型调用(this.、confirm),不用组件引入方式。

四、目录结构拆分规范(企业通用)

plaintext
 
 
src
├─ views           # 页面级组件,路由对应页面
│  ├─ user
│  │  ├─ index.vue
│  │  └─ components  # 当前页面私有业务组件
│  └─ order
├─ components
│  ├─ common        # 全局公共基础组件(所有页面可复用)
│  │  ├─ PagePagination
│  │  ├─ UploadFile
│  │  └─ EmptyData
│  └─ business      # 业务通用组件(多个模块复用)
│     ├─ OrderCard
│     └─ UserSelect
└─ store           # 全局状态,存放用户、权限、字典等全局数据
 

命名规范避坑

  1. 组件名:大驼峰 UserTable.vue,避免小写、短缩写模糊命名;
  2. 页面内私有组件统一放在当前页面的 components 文件夹,不要和全局组件混放;
  3. 公共组件必须写注释、默认 props、入参校验(props 校验)。

五、拆分避坑心得(踩坑总结)

1. 不要过度拆分(拆分不是越细越好)

  • 一段 UI + 逻辑只有几十行,且只在当前页面用一次,没必要强行拆组件;
  • 过度拆分会导致:父子传参满天飞、业务逻辑分散、排查问题需要来回跳转多个文件,维护成本飙升。
判断要不要拆:
  • 代码 > 300 行 / 多处复用 / 独立业务模块 → 拆
  • 仅少量 UI 片段、只使用一次、几十行代码 → 不拆,用模板片段即可。

2. 别把业务逻辑下沉到子组件

子组件只负责 UI 展示,接口请求、权限判断、分页查询、数据处理尽量放在父页面。
 
如果子组件自己发请求,后期排查接口来源、统一接口拦截、权限管控会非常混乱。

3. props 一定要做类型校验

拆分后多人协作极易传错参数,必须约束类型、默认值:
js
 
运行
 
 
 
props: {
  tableData: {
    type: Array,
    default: () => []
  }
}
 

4. 插槽灵活预留,提升组件通用性

封装表格、弹窗、卡片类组件时,预留头部、尾部、操作列插槽,避免每次 UI 微调就要改组件源码。

5. 纯展示组件尽量做「无状态组件」

只依赖 props 渲染,内部不维护 data,不修改外部数据,可做到极致复用,方便缓存、性能优化。

六、极简拆分口诀

  1. 一页超三百,立刻拆组件;
  2. 多处重复用,抽到公共区;
  3. 父管接口与状态,子管渲染与事件;
  4. 弹窗表单单独抽,不要堆在页面里;
  5. 能少拆不多拆,适度分层才好维护;
  6. 全局状态放 Vuex,局部数据父子传参。

七、进阶优化心得

  1. 高度相似的组件,通过 props 配置化(type、status)来控制不同 UI,不用重复新建多个组件;
  2. 通用组件支持属性透传($attrs),不用每一个属性都手动定义 props;
  3. 复杂计算放在父页面 computed 处理,不要让多个子组件重复计算;
  4. 拆分同时做好组件懒加载,路由懒加载、异步组件,优化首屏性能。
需要我给一份「后台管理系统标准组件目录 + props 规范模板」吗?
posted @ 2026-06-26 12:25  飘来荡去evo  阅读(41)  评论(0)    收藏  举报