一次重构让我把Vue组件从2000行拆分到200行的方法
接手一个 2000 行的 Vue 组件是什么体验?打开文件,滚动条瞬间缩成一个小点;搜索一个变量,满屏都是它的身影;改一个按钮文案,结果影响了下拉框的选项。更可怕的是,所有人都知道它有问题,但没人敢动——因为没人能说清它到底在干什么。
去年我就遇到了这样一个“上帝组件”:它同时负责搜索表单、数据表格、分页、新增编辑弹窗、导入导出、权限校验和埋点上报。每次需求进来,都是在这 2000 行里继续加代码。直到一次线上事故后,我下定决心重构。最终,主组件只剩 200 行左右。下面把我用的方法拆开讲,希望能帮到正在面对类似困境的你。
别急着删代码,先画一张职责地图
很多人一上来就新建文件、复制粘贴,结果越拆越乱。我的第一步是:不写一行新代码,只做标记。我把 2000 行按功能块用注释分隔,然后统计每块的行数和依赖关系。比如:
- 搜索表单:约 300 行,含 8 个字段、2 个联动逻辑
- 表格列定义与渲染:约 500 行,含自定义插槽、格式化、排序
- 分页与批量操作:约 200 行
- 新增/编辑弹窗:约 600 行,含表单校验、动态字段、提交逻辑
- 权限、埋点、导入导出:约 400 行
画完这张图,组件的边界就清晰了。重构不是“把它变小”,而是“让每个部分只做一件事”。
拆出纯展示组件,让 UI 与逻辑分离
最先拆的是表格和弹窗。表格只接收 `list`、`columns`、`loading`,通过插槽暴露自定义单元格;弹窗只接收 `visible`、`mode`、`initialData`,通过 `@submit` 向外抛事件。这样做的好处是,展示组件可以独立测试,甚至可以用 Storybook 单独预览。
比如原来的表格列定义里混杂了权限判断和点击跳转,我把它抽成 `columns.js`,每一列只保留 UI 描述,权限和跳转逻辑放到父组件或组合式函数里。表格组件从 500 行降到 80 行,而且复用到了其他三个页面。
用组合式函数收拢状态与副作用
Vue 3 的 Composition API 是拆逻辑的利器。我把搜索条件、分页参数、请求状态、防抖逻辑抽成 `useUserList.js`,把弹窗的打开、关闭、表单校验、提交抽成 `useUserForm.js`。每个函数只暴露必要的 `ref` 和方法,主组件通过 `setup` 组合它们。
const { list, loading, pagination, search, reset } = useUserList()
const { dialogVisible, formData, openCreate, openEdit, submit } = useUserForm()
这一步做完,主组件的 `<script>` 从 1200 行降到了 300 行左右。更重要的是,逻辑可以单独写单元测试,不用再挂载整个组件。
主组件只做“指挥”,不做“演奏”
拆到最后,主组件的职责只剩下三件事:组装子组件、传递 props 和事件、处理跨模块的协调。比如搜索后重置分页、提交成功后刷新列表并关闭弹窗。这些协调逻辑本身不会太长,200 行足够。
我给自己定了一个规则:主组件里不允许出现超过 20 行的函数,不允许直接写 axios 请求,不允许写复杂的表单校验。一旦违反,就说明还有东西没拆干净。
重构中的三个坑
第一,别一次性全拆。我按“搜索 → 表格 → 分页 → 弹窗”的顺序,每拆一块就提交一次,保证随时可回滚。第二,别过度抽象。不是所有东西都要抽成组件,有些只有两行模板的片段留在原地反而更清晰。第三,别忽略测试。重构前我补了关键路径的单元测试和 E2E 用例,否则改完根本不敢上线。
从 2000 行到 200 行,真正变的不是数字,而是心智负担。以前改一个字段要通读全文,现在打开对应的组合式函数或子组件就行。重构不是一次性的英雄主义,而是一种持续的习惯:每次加需求前,先问自己——这块逻辑应该放在哪里?
如果你也正被一个巨型组件折磨,不妨从明天开始,先画一张职责地图。不用追求完美,先拆出第一个纯展示组件,你会发现,200 行并没有那么遥远。
转载请注明出处,版权归原作者所有。
管理员
黑卡会员