You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化JS+HTML海量数据场景下的搜索性能?

搜索功能性能优化问题

当前代码可在HTML页面生成容器并实现搜索匹配显示/隐藏功能,但当数据量达到2000条及以上时,搜索操作会出现5-10秒的卡顿,需要优化搜索算法提升速度。


原实现代码

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="emotes_area"  id="emotes_area">
        </div>
        
        <input class="search_input" id="input_search" type="text" placeholder="Search Something...">
        

</body>

</html>

CSS

.emotes_area{
  position: absolute;
  width: 404px;
  height: 703px;
  top: 165px;
  left: 62px;
  flex-wrap: wrap;
  overflow-y: auto;
  overflow-x: hidden;
}

.emotes_area::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(255, 255, 255, 0.25);
background-color: rgba(255, 255, 255, 0.25);
}

.emotes_area::-webkit-scrollbar
{
width: 1px;
background-color: #00000000;
}

.emotes_area::-webkit-scrollbar-thumb
{
-webkit-box-shadow: inset 0 0 6px rgba(255, 255, 255, 0.25);
background-color: rgb(255, 255, 255);
}

.emote_container{
  position: relative;
  width: 123px;
  height: 131px;
  flex-shrink: 0;
  background: radial-gradient(82.29% 82.29% at 50% 50%, rgba(143, 143, 143, 0.5) 10%, rgba(255, 255, 255, 0.00) 90%);
  box-shadow: inset 0 0 0 1px  #81818173;
  display: flex;
  top: 0px;
  cursor: pointer;
  margin: 2.7px;
}

/* New CSS */
.parent-container {
    display: flex;
    flex-wrap: wrap;
}
.child {
    max-width: 33.33%;
}

JavaScript

document.addEventListener("DOMContentLoaded", function () {
  var count = 0;
  var countOuter =0;
  var table=document.createElement("div");
  table.classList.add("parent-container")
  for(var i=0;i<(200);i++){ //SATIR
    
var tr=document.createElement("div");
tr.classList.add("child", "childno")
tr.classList.add(countOuter)
    table.appendChild(tr);
            tr.innerHTML=
            '<div id="'+count+'" class="emote_container">'+ 
                '<span id="'+count+'"  class="emote_name_lbl"> '+count+' </span>'+ 
            '</div>';
        count++;
        countOuter++;
    
    }
    document.getElementById("emotes_area").innerHTML="";
    document.getElementById("emotes_area").appendChild(table);
});


document.getElementById("input_search").addEventListener("input", function() {
  var searchValue = this.value.toLowerCase(); // Get the lowercase value of the input
  var emoteContainers = document.getElementsByClassName("child");

  for (var i = 0; i < emoteContainers.length; i++) {
  var emoteName = emoteContainers[i].getElementsByClassName("emote_name_lbl")[0].innerText.toLowerCase();

  if (emoteName.includes(searchValue)) {
      emoteContainers[i].style.display = "flex"; // Show the emote container
  } else {
      emoteContainers[i].style.display = "none"; // Hide the emote container
  }
  }
});

优化方案

1. 提前缓存数据,避免重复DOM查询

原代码每次搜索都要反复查询DOM元素,这是卡顿的核心原因。初始化时把每个表情的DOM元素和名称缓存到数组里,后续搜索直接遍历数组即可。

修改后的初始化代码:

let emoteData = []; // 全局缓存数组,存储元素与对应名称
document.addEventListener("DOMContentLoaded", function () {
  let count = 0;
  const table = document.createElement("div");
  table.classList.add("parent-container");
  const fragment = document.createDocumentFragment(); // 用文档片段减少DOM重排

  for(let i=0;i<2000;i++){ 
    const tr = document.createElement("div");
    tr.classList.add("child", "childno");
    tr.innerHTML = `
      <div id="${count}" class="emote_container">
        <span id="${count}" class="emote_name_lbl"> ${count} </span>
      </div>
    `;
    fragment.appendChild(tr);
    // 缓存当前元素和小写名称,避免后续重复查询
    emoteData.push({
      element: tr,
      name: `${count}`.toLowerCase()
    });
    count++;
  }

  table.appendChild(fragment); // 一次性插入所有元素,减少DOM操作
  document.getElementById("emotes_area").innerHTML = "";
  document.getElementById("emotes_area").appendChild(table);
});

2. 优化搜索事件,加入防抖减少触发频率

输入时每打一个字就触发一次搜索会造成不必要的性能浪费,加入防抖函数,等待输入停止一段时间后再执行搜索,同时直接遍历缓存数组操作元素。

修改后的搜索事件代码:

// 防抖函数:延迟执行,避免输入时频繁触发
function debounce(func, delay = 200) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => func.apply(this, args), delay);
  };
}

document.getElementById("input_search").addEventListener("input", debounce(function() {
  const searchValue = this.value.toLowerCase();
  // 直接遍历缓存数组,跳过DOM查询
  emoteData.forEach(item => {
    if (item.name.includes(searchValue)) {
      item.element.style.display = "flex";
    } else {
      item.element.style.display = "none";
    }
  });
}, 200));

3. 用CSS类切换显示状态(可选)

直接修改style.display不如切换CSS类高效,定义一个隐藏类,搜索时切换类即可:

/* 新增CSS类 */
.child.hidden {
  display: none !important;
}

然后修改搜索逻辑:

emoteData.forEach(item => {
  if (item.name.includes(searchValue)) {
    item.element.classList.remove("hidden");
  } else {
    item.element.classList.add("hidden");
  }
});

4. 避免使用动态HTMLCollection

原代码中getElementsByClassName返回的是动态集合,每次访问都会重新查询DOM,性能极低。换成querySelectorAll获取静态NodeList也能提升性能,但最优方案还是用前面的缓存数组。


内容的提问来源于stack exchange,提问作者Mehmet Akgün

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 20:23:10