JavaScript input事件大数据搜索时输入字符卡顿问题
输入框海量数据实时检索卡顿优化方案
现有实现卡顿的核心原因是两点:一是每次输入都全量遍历整个数组,遍历过程属于JS长任务,会占满单线程主线程,导致输入事件无法被及时响应;二是每次循环都重复对name字段做小写转换,做了很多无意义的重复计算。可以按下面的步骤逐步优化:
- 第一步:做前置数据预处理
页面初始化的时候就把所有待检索数据的name字段转成小写存好,不用每次触发搜索都在循环里重复转格式,把重复计算的开销一次性消化掉,同时提前缓存DOM元素,避免每次触发事件都重复查询DOM:
// 初始化阶段执行一次即可 const searchData = obj.map(item => ({ origin: item, lowerName: item.name.toLowerCase() })) const inputEl = document.querySelector('input')
- 第二步:加防抖过滤无效检索
连续快速输入的时候,中间输入过程的检索都是没有意义的,加200-300ms的防抖,等用户输入停顿后再执行真正的检索逻辑,大幅减少冗余任务:
let searchTimer = null inputEl.addEventListener('input', () => { clearTimeout(searchTimer) searchTimer = setTimeout(() => { const keyword = inputEl.value.toLowerCase().trim() console.clear() if (!keyword) return const matchRes = [] for (let i = 0; i < searchData.length; i++) { if (searchData[i].lowerName.includes(keyword)) { matchRes.push(searchData[i].origin.name) } } matchRes.forEach(name => console.log(name)) }, 300) })
- 第三步:超大数据集分片执行,避免阻塞主线程
如果数据量达到10w条以上,单次全量遍历本身耗时就会超过浏览器单帧刷新阈值(16ms),这时候把遍历任务拆成多个小块,每处理1000条左右就把主线程交还给浏览器响应交互,完全不会出现输入阻塞的情况:
function chunkSearch(keyword, chunkSize = 1000) { const matchRes = [] let currentIdx = 0 function runOneChunk() { const endIdx = Math.min(currentIdx + chunkSize, searchData.length) for (let i = currentIdx; i < endIdx; i++) { if (searchData[i].lowerName.includes(keyword)) { matchRes.push(searchData[i].origin.name) } } currentIdx = endIdx if (currentIdx < searchData.length) { // 等浏览器空闲的时候再处理下一片,不阻塞输入 requestIdleCallback(runOneChunk) } else { console.clear() matchRes.forEach(name => console.log(name)) } } runOneChunk() } // 防抖逻辑里替换成调用分片搜索即可 inputEl.addEventListener('input', () => { clearTimeout(searchTimer) searchTimer = setTimeout(() => { const keyword = inputEl.value.toLowerCase().trim() console.clear() if (!keyword) return chunkSearch(keyword) }, 300) })
- 第四步:固定数据集可以加索引进一步提速
如果待检索的obj数组是固定不频繁更新的,可以提前给name字段建前缀索引或者Trie树结构,把检索的时间复杂度从O(n)降到和关键词长度相关的O(k),就算是百万级数据也能做到毫秒级返回结果。
注意:检索结果不要匹配到一条就打一条console.log,先收集齐所有匹配项再统一输出,频繁的控制台打印也会拖慢执行速度。
内容的提问来源于stack exchange,提问作者Zainul Abideen
相关产品推荐
相关产品推荐

