第 6 课:第二轮真实重构,拆出任务表格组件

这一课我们继续做真的页面重构。

这次不是再讲抽象原则,

而是继续把任务页往"清晰组合页"的方向推进。

这次新增的核心组件是:

  • src/components/tasks/TaskTable.vue

同时更新了:

  • src/views/TasksView.vue

先讲结论

这次为什么优先拆表格,而不是先拆弹窗?

因为表格满足这三个条件:

  1. 它已经是一整块独立区域
  2. 它的输入非常清晰,只需要任务列表
  3. 它虽然有一点显示逻辑,但状态复杂度仍然可控

而弹窗目前还同时牵涉:

  • 弹窗开关
  • 表单状态
  • 校验
  • 提交
  • 重置

它的复杂度明显更高,所以不适合比表格更早拆。


这次重构涉及哪些文件

新增文件

  • src/components/tasks/TaskTable.vue

更新文件

  • src/views/TasksView.vue
  • docs/README.md

为什么表格是第二轮最合适的目标

在上一轮重构后,TasksView.vue 还剩下两块明显比较重的区域:

  1. 任务表格
  2. 新增任务弹窗

如果继续按照"先简单、后复杂"的策略,

表格显然更合适。

因为表格虽然模板长一点,但它本质上还是:

接收数据 -> 按规则渲染

而弹窗更像:

局部小业务系统

这两者不是一个复杂度等级。

所以这次优先拆表格,是一次很稳的决策。


TaskTable.vue 的职责是什么

当前这个组件的职责非常清楚:

  1. 接收任务列表
  2. 渲染表格
  3. 渲染状态标签
  4. 渲染优先级标签
  5. 当列表为空时显示空状态

你会发现,这个组件现在的定位仍然是:

展示型组件为主,附带少量显示规则

它和弹窗最大的区别就在这里。


这个组件的输入是什么

它当前只有一个核心输入:

  • tasks

也就是说,父组件已经把"筛选后的最终结果"准备好了,

表格组件只负责显示。

这是一种非常理想的结构,因为它让组件边界特别清楚:

  • 父组件负责算结果
  • 子组件负责画结果

这个组件为什么还保留了两个函数

你会看到 TaskTable.vue 内部有两个辅助函数:

  • getStatusType
  • getPriorityType

这两个函数本质上不是业务逻辑,

而是"展示规则翻译器"。

它们做的是:

  • 业务值"已完成" -> UI 颜色 success
  • 业务值"高" -> UI 颜色 danger

所以把它们放进表格组件是合理的。

因为这些函数描述的是:

表格这一块应该怎么显示

而不是:

页面整体业务该怎么运转

这就是为什么这次我把它们从 TasksView.vue 下沉到了 TaskTable.vue。


这一步很值得你学

很多初学者做组件拆分时容易只会"搬模板",

但不会判断哪些函数也应该一起搬走。

你现在要学会一件事:

如果一个函数只服务某个组件的显示规则,它通常就适合跟着组件一起下沉

这就是更完整的组件化思维。


TasksView.vue 这次又轻了什么

拆表格之后,父组件不再负责:

  • 表格列模板
  • 状态标签插槽
  • 优先级标签插槽
  • 空状态显示
  • 标签颜色映射函数

它现在更专注于:

  • 管主数据
  • 管筛选条件
  • 管弹窗和表单
  • 计算筛选结果
  • 计算统计卡片
  • 组合子组件

这说明 TasksView.vue 又更像一个"页面容器"了。


现在的任务页已经接近什么结构

现在 TasksView.vue 基本已经有了这种层次:

vue 复制代码
<TaskPageHeader />
<TaskStatsCards />
<TaskFilterBar />
<TaskTable />
<el-dialog ... />

这意味着:

  • 页面头部独立了
  • 统计区独立了
  • 筛选区独立了
  • 表格区独立了
  • 当前只剩弹窗还是页面里最重的一块

这就是非常典型的"渐进式收缩父页面"的过程。


为什么 TaskTable.vue 仍然算比较简单

虽然表格看起来行数不少,

但它的复杂度主要来自"模板长度",而不是"状态关系"。

它没有自己单独维护:

  • 筛选状态
  • 提交状态
  • 表单状态
  • 打开关闭状态

所以它比弹窗简单得多。

这也是为什么:

模板长,不一定最复杂;状态多,通常才是真的复杂

这是你以后判断重构优先级时非常重要的一条经验。


这次重构最值得你学的设计判断

1. 先拆"输入明确"的区域

表格的输入非常明确:

  • 就是任务列表

这种组件最容易设计边界。


2. 展示规则可以跟着展示组件走

状态颜色、优先级颜色这类规则,不一定要永远留在父组件。

如果它们只服务当前展示块,

跟着展示组件一起下沉往往更合理。


3. 父组件不要继续背所有模板细节

父组件越像"总控层",

整个页面就越容易读。

这次重构的实际效果,就是让 TasksView.vue 继续远离"大模板 + 大逻辑"的方向。


这次重构后,你应该怎么理解父子分工

父组件 TasksView.vue

负责:

  • 主任务数据
  • 筛选条件
  • 统计计算
  • 新增任务逻辑
  • 弹窗逻辑
  • 页面级编排

子组件 TaskTable.vue

负责:

  • 表格结构
  • 标签显示
  • 空状态显示

你可以把它们之间的关系理解成:

父组件决定要显示什么,子组件决定怎么显示


这次重构最容易忽略的一个点

有些人会觉得:

"表格只是搬出去,没什么本质变化。"

其实不是。

真正的变化在于:

  • 父组件少了一整块模板噪音
  • 展示规则开始就近收口
  • 页面职责开始更明确

这就是为什么真实项目里,

看起来"只是拆了一个组件",

但长期维护体验会明显不同。


你现在应该能回答的 10 个问题

  1. 为什么表格比弹窗更适合作为第二轮重构目标?
  2. TaskTable.vue 的核心输入是什么?
  3. 为什么它当前仍然算低复杂度组件?
  4. getStatusType 和 getPriorityType 为什么适合下沉到表格组件?
  5. 父组件拆掉表格后,少承担了哪些内容?
  6. 现在的 TasksView.vue 为什么更像页面容器了?
  7. 为什么"模板长"和"状态复杂"不是一回事?
  8. 什么样的函数适合跟着展示组件一起移动?
  9. 当前任务页里下一块最重的区域是什么?
  10. 为什么渐进式重构会让页面越来越清晰?

这节课的动手练习

练习 1

打开 TaskTable.vue,回答:

  • 它负责什么
  • 它不负责什么

目的:

训练你判断组件边界。


练习 2

对照看:

尝试自己说出:

  • 哪些逻辑还在父组件里
  • 哪些逻辑已经下沉到子组件里

目的:

训练你看懂"职责迁移"。


练习 3

试着自己判断:

如果以后要给表格加"编辑"按钮和"删除"按钮,

它们更适合:

  • 直接写在 TaskTable.vue
    还是
  • 继续放在 TasksView.vue

并给出理由。

目的:

开始练习"组件未来扩展方向"的判断。


这节课的复习结论

把这次第二轮重构压缩成 8 句话:

  1. 表格是第二轮重构最合适的对象,因为它边界清晰、输入明确。
  2. TaskTable.vue 主要是展示组件,复杂度明显低于弹窗表单。
  3. 父组件继续保留页面级业务和状态管理。
  4. 子组件负责表格结构、标签显示和空状态。
  5. 只服务展示的辅助函数,通常适合跟着展示组件一起下沉。
  6. 父组件拆掉表格后,页面结构又清晰了一层。
  7. 模板长不一定最复杂,状态关系复杂才更值得谨慎处理。
  8. 当前任务页离真正干净的组合页又近了一步。
相关推荐
FungLeo6 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
Csvn7 小时前
并发模式:让渲染学会排队、插队和让路
前端
可乐鸡翅yeah_8 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
Flynt8 小时前
Linear 用 1000 个 PR 换掉 styled-components,我写了 200 个按钮,把这笔账复现了一遍
前端·css·preact
JavaGuide9 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel9 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘10 小时前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马10 小时前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut10 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia12311 小时前
实现完整 Tool Dispatcher
开发语言·前端