如何从字典中填充大型数据列表(~2000 项)

How to populate a large datalist (~2000 items) from a dictionary

现在我正在使用以下代码,但在 Chrome 上需要大约 10 秒,在 IE11 上需要大约 2 分钟,这是它最常被使用的地方。

for (var key in dict) {
    if (dict.hasOwnProperty(key)) {
        combo.innerHTML += "<option value=\"" + dict[key] + "\">" + key + "</option>";
    }
}

我正在阅读本教程:http://blog.teamtreehouse.com/creating-autocomplete-dropdowns-datalist-element 建议在处理较大数量时像这样使用 ajax,但我不确定大是指 100 件还是 100,000 件。

var request = new XMLHttpRequest();

request.onreadystatechange = function(response) {
  if (request.readyState === 4) {
    if (request.status === 200) {

      var jsonOptions = JSON.parse(request.responseText);

      jsonOptions.forEach(function(item) {

        var option = document.createElement('option');
        option.value = item;
        dataList.appendChild(option);

      });

    } else {
      console.log("Failed to load datalist options");
    }
  }
};

request.open('GET', 'html-elements.json', true);
request.send();

我一直在尝试通过将 request.responseText 替换为 JSON.parse(JSON.stringify(dict)); 来使其适用于字典,但我 运行 遇到了问题,无法让它开始请求with 因为它不在文件中。

我应该怎么做?如果我不应该为此使用 DataList,您推荐什么替代方案?

提前致谢。

您可以提高性能的一个领域是文档片段,因为写入 DOM 很慢。

var frag = document.createDocumentFragment();

for (var key in dict) {
    if (dict.hasOwnProperty(key)) {
        var option = document.createElement("OPTION");
        option.textContent = key;
        option.value = dict[key];
        frag.appendChild(option);
    }
}

combo.appendChild(frag);

获得更好性能的即时方法是先构建 HTML 字符串,然后将其分配给内部 HTML.

var htmlStr = '';
for (var key in dict) {
    if (dict.hasOwnProperty(key)) {
        htmlStr += "<option value=\"" + dict[key] + "\">" + key + "</option>";
    }
}
combo.innerHTML = htmlStr;

差异巨大:http://jsperf.com/string-append-vs-dom

DOM 是出了名的慢。您可以尝试手动过滤并仅显示前 X 个元素。正如 znap026 指出的那样,使用文档片段也有助于加快速度。

"use strict";

var data = Object.getOwnPropertyNames(window).sort(),
  datalist = document.getElementById("datalist"),
  input = document.getElementById("input");
  
const processedData = Object.fromEntries(data.map(d => [d.toLowerCase(), d]));

function search() {
  var term = input.value.toLowerCase();
  var found = 0;
  var frag = document.createDocumentFragment();

  for (var child of [].slice.apply(datalist.childNodes)) {
    datalist.removeChild(child);
  }

  for (var searchable in processedData) {
    if (searchable.indexOf(term) === 0) {
      let item = processedData[searchable];
      let option = document.createElement("option");
      option.value = item

      frag.appendChild(option);
      if (++found > 10) break;
    }
  }

  datalist.appendChild(frag);
}

search();
input.addEventListener("input", search);
<input id="input" list="datalist" placeholder="window properties"/>
<datalist id="datalist"></datalist>

您还可以通过从输入中分离数据列表并在填充后再次附加它来提高性能:

"use strict";

// init
const values = Object.getOwnPropertyNames(window);
const datalist = document.getElementById("datalist");
const arr = values.map(k => new Option(k));

let start = performance.now();
datalist.replaceChildren(...arr);
console.log('plain replace:', performance.now() - start);

// reset
datalist.replaceChildren(...[]);

start = performance.now();
datalist.setAttribute("id", undefined);
datalist.replaceChildren(...arr);
datalist.setAttribute("id", "datalist");
console.log('replace with detach and attach:', performance.now() - start);
<input list="datalist" />
<datalist id="datalist"></datalist>