Skip to content

092. 单选、多选、列钩子与行事件钩子

学习目标

这一节开始实现单选、多选,并引入事件钩子。

学完后,你应该能理解:

  • 单选为什么和表单编辑有关;
  • 多选为什么会影响批量操作和父子表;
  • 列配置为什么也要变成钩子变量;
  • 查询表单显示为什么要放进配置;
  • 事件钩子如何替代统一 handler;
  • 为什么点击按钮或输入框时不能触发行点击事件。

单选的作用

表格单选不是只为了选中一行。

它还会服务很多后续功能。

例如:

  • 表单编辑;
  • 查看详情;
  • 父子表联动;
  • 当前行上下文;
  • 外部按钮操作当前行。

如果表单编辑按钮不放在每一行里,就需要通过单选拿到当前行。

所以单选能力是表单编辑服务的前置基础。

单选默认开启

单选会和索引列融合。

也就是说,不一定单独再加一列显示单选。

索引列既可以显示序号,也可以承载当前行选中状态。

这样表格不会多出一列,视觉更紧凑。

单选默认强制开启,是因为后面很多功能都依赖当前行。

多选的作用

多选用于批量操作。

例如:

  • 批量删除;
  • 批量导出;
  • 批量编辑;
  • 智能新建时选择多条参考数据。

多选也可以影响父子表。

当主表选中行发生变化时,子表可以根据当前选中行重新加载数据。

所以单选和多选都不是孤立功能。

它们是表格状态体系的一部分。

列也需要钩子变量

前面已经有:

  • 渲染钩子;
  • 按钮钩子变量。

这一节继续把列配置也变成钩子变量。

原因是不同模块可能都要往表格里加列。

例如:

  • 索引列模块添加索引列;
  • 多选模块添加选择列;
  • 操作列模块添加操作列;
  • 业务模块添加自定义列。

如果列只来自页面配置,就无法让模块灵活插入系统列。

列顺序 seq

列配置里有 seq

它控制列显示顺序。

默认值可以是 0

左固定列和右固定列还可以自动调整顺序。

大致规则是:

  • 越小越靠左;
  • 越大越靠右;
  • 左固定列适合更小顺序;
  • 右固定列适合更大顺序。

这样索引列、选择列、操作列都能按稳定顺序插入。

查询表单显示配置

查询表单模块增加了显示控制。

例如:

  • 是否默认展开查询表单;
  • 是否显示查询表单按钮。

默认可以不展开。

页面配置里可以开启。

这样不同页面可以决定查询表单是否默认出现。

如果某个页面不需要查询按钮,也可以通过配置隐藏。

事件钩子

表格里很多模块都可能需要监听行事件。

例如:

  • 双击行进入编辑;
  • 单击行选中;
  • 点击行刷新子表;
  • 点击行触发详情展示。

如果都写到一个统一 handler 里,后面会越来越臃肿。

所以引入事件钩子。

每个模块监听自己关心的事件。

事件钩子的结构

事件钩子内部维护一个函数数组。

每个监听者往数组里注册自己的处理函数。

例如:

ts
autoTable.hooks.onClickRow.use(handler)
autoTable.hooks.onDoubleClickRow.use(handler)

当事件发生时,事件钩子依次执行这些 handler。

这和 Axios 拦截器有点像。

一组函数按顺序处理同一个事件数据。

监听函数的参数类型

行点击事件需要传递几个信息:

  • 鼠标事件;
  • 行数据;
  • 行索引。

所以事件参数可以理解成:

ts
{
  event: MouseEvent
  record: RowData
  index: number
}

监听函数接收到这些数据后,就能做自己的业务逻辑。

例如编辑、选中、刷新子表。

注册和清理监听函数

事件钩子使用 useEffect 维护监听函数。

当传入的 handler 变化时:

  1. 把新的 handler 放进数组;
  2. 在清理函数里移除旧 handler。

这样组件卸载或依赖变化后,不会留下旧监听。

否则同一个事件可能被重复触发多次。

双击编辑迁移到事件钩子

原来双击行进入编辑,是通过统一 handler 模块处理。

现在可以改成事件钩子。

状态模块或编辑模块监听 onDoubleClickRow

触发时判断配置:

ts
if (runningConfig.editRowOnDoubleClick) {
  autoTable.methods.editRecord(record)
}

这样双击编辑变成一个模块行为。

以后其他模块也可以监听同一个双击事件。

统一 handler 可以移除

引入事件钩子后,统一 handler 模块的职责会变少。

行组件只负责派发事件。

具体谁响应事件,由各个模块自己决定。

这样模块之间更解耦。

新增功能时,不需要持续修改一个越来越大的 handler 文件。

行组件派发事件

表格行组件监听原生点击和双击。

触发后,它把事件数据交给事件钩子。

例如:

ts
autoTable.hooks.onClickRow.exec({
  event,
  record,
  index,
})

双击同理。

这样行组件不关心点击之后具体做什么。

它只负责把事件发出去。

忽略按钮和输入框点击

点击表格行时,要排除一些元素。

例如:

  • 按钮;
  • 输入框。

如果用户双击按钮,不应该触发行双击编辑。

如果用户点击输入框,也不应该触发行选择或行编辑。

所以事件派发前,要检查点击目标。

如果目标元素是 buttoninput,就直接跳过。

这能避免很多交互误触。

事件钩子的执行结果

事件钩子后面还会更复杂。

它可以把上一个函数的执行结果传给下一个函数。

这要求监听函数的入参和出参类型一致。

这种设计可以让事件数据经过多个模块逐步加工。

当前先理解最基础的监听和派发即可。

后续会继续用它改造更多行为。

这一节的核心

这一节把表格的扩展能力继续推进。

关键变化是:

  • 单选、多选成为表格基础状态;
  • 列配置也进入钩子变量体系;
  • 查询表单显示由配置控制;
  • 行点击和双击改成事件钩子;
  • 双击编辑从统一 handler 转为模块监听;
  • 行组件只负责派发事件,不负责决定业务行为。

这让后续表单编辑、父子表联动、批量操作都能建立在更灵活的事件体系上。

AI Agent 课程学习文档。