用 set 存 id 是提升多选组件响应速度最直接有效的手段——它把“判断某行是否被选中”这个高频操作,从 o(n) 降到了 o(1)。

为什么不用数组存选中项?
数组的 includes、indexOf、find 等方法都需要遍历查找。当用户勾选了 500 条数据,每次渲染一行都要遍历 500 次,表格有 100 行可见项,仅一次重绘就触发 5 万次比对。浏览器卡顿、滚动掉帧几乎必然发生。
Set 的 has() 方法底层基于哈希表,无论已选 10 个还是 10000 个 ID,查询耗时基本恒定。
如何初始化和更新 Set?
在组件 setup 或 state 初始化阶段创建:
const selectedIds = new Set();
点击切换某行时,不要 push 或 filter 数组,而是直接操作 Set:
- 检查是否存在:selectedIds.has(id)
- 存在则删除:selectedIds.delete(id)
- 不存在则添加:selectedIds.add(id)
无需维护副本或深拷贝,Set 本身是可变引用,状态变更后只需触发一次响应式更新(如 Vue 的 ref.value = selectedIds)。
渲染时如何高效判断勾选状态?
在模板或 JSX 中,直接使用 has() 判断即可:
避免写成 selectedItems.some(i => i.id === item.id) 或 selectedItems.map(i => i.id).includes(item.id) 这类低效表达式。
配合全选/半选逻辑更省力
全选按钮的状态(全选、半选、未选)不应每次点击都遍历全部数据。可结合 Set 和当前页数据动态计算:
- 当前页全选:当前页每行 ID 都在 Set 中 → currentPageData.every(row => selectedIds.has(row.id))
- 当前页有选中:当前页至少一行 ID 在 Set 中 → currentPageData.some(row => selectedIds.has(row.id))
- 总选中数:直接读 selectedIds.size,无需 count 或 length
这些计算只依赖当前页数据量(通常 20–100 条),与总数据量无关,彻底避开性能陷阱。










