用 localStorage 缓存高频筛选结果,预构建字段索引加速交集查询,requestIdleCallback 延迟非关键渲染,节流 change 事件触发,四者协同保障 60fps。

用 localStorage 缓存筛选结果,避免重复计算
用户反复切换相同条件组合时,每次都重新遍历整个数据集,会明显卡顿。把 JSON.stringify(conditions) 作为 key,把计算结果(如汇总值、过滤后数组)存进 localStorage,下次命中直接返回。
注意:数值型字段要统一转成字符串再拼接,否则 {price: 100} 和 {price: "100"} 会被当成不同 key;日期字段建议用 toISOString() 标准化格式。
- 只缓存高频组合(比如最近 5 次操作),避免
localStorage溢出 - 当原始数据更新时,需主动清空相关缓存(可用版本号或时间戳标记)
- 移动端 Safari 对
localStorage写入有同步阻塞,大数据量建议改用indexedDB
客户端过滤前先做数据分块与提前剪枝
原始数据超过 5000 行时,filter() 一次遍历仍可能卡住主线程。可在初始化阶段按关键筛选字段(如 region、category)预分组,生成索引结构:
const index = {
region: { 华东: [0, 2, 5], 华南: [1, 3] },
category: { 电子: [0, 1], 家居: [2, 3, 5] }
};
筛选时先取交集索引(如 intersection(index.region.华东, index.category.电子)),再查原始数组,跳过 90% 无用遍历。
立即学习“前端免费学习笔记(深入)”;
- 索引构建是一次性开销,适合静态或低频更新的数据
- 交集运算用 Set 比数组
filter().includes()快一个数量级 - 不要为所有字段建索引——只选 2~3 个高频筛选字段
用 requestIdleCallback 延迟非关键渲染
筛选后不仅要更新汇总数字,还要高亮匹配行、刷新分页、重绘图表……这些不全需要立刻完成。把非首屏、非交互必需的更新(如“共匹配 127 条”文字、统计图重绘)包进 requestIdleCallback:
requestIdleCallback(() => {
updateSummaryCard();
renderChart();
});
浏览器会在空闲帧执行,避免阻塞用户点击下拉框或滚动页面。
- 务必加超时兜底:
requestIdleCallback(fn, { timeout: 2000 }),防止任务被永久挂起 - 移动端低端机上
requestIdleCallback支持率不高,需降级为setTimeout(fn, 0) - 别在里面做 DOM 批量插入——仍要用
DocumentFragment或虚拟列表
避免在 change 事件里直接调用 heavyFilter()
用户拖动滑块或连点复选框时,change 事件可能高频触发,导致多次冗余计算。必须加节流:
用 setTimeout + 标志位最轻量:
let pending = false;
function onFilterChange() {
if (pending) return;
pending = true;
setTimeout(() => {
doFilter();
pending = false;
}, 150);
}
- 150ms 是平衡响应与性能的经验值,比防抖更合适筛选场景
- 如果用户快速切换多个条件,最后那次触发必须保留,不能被节流丢弃
- 不要依赖 lodash.throttle —— 多一个 4KB 的依赖不值得



















