【问题标题】:Efficiently populate Select Elements in 2019在 2019 年有效填充 Select Elements
【发布时间】:2019-08-21 02:30:05
【问题描述】:

我必须通过 DOM 和 Javascript 动态填充 HTML 选择元素。

我做了一些研究,一切正常,但我还有一些问题。

我发现了 2 个 stackoveflow 帖子和另一个关于如何填充选择元素的非堆栈博客帖子:

所有 3 篇文章的年龄都在 8 到 10 岁之间。由于旧版浏览器无法使用“innerHTML”DOM 属性,他们似乎更喜欢下面讨论的某种技术。

所有这 3 篇文章都指示使用以下方法通过 DOM 填充选择元素: document.createElement("option").

许多人尝试使用 'Element.innerHTML' DOM 属性来使用 STRING 选项填充选择元素,而不是使用 document.createElement("option")。

显然,这些人随后被指示使用 document.createElement("option") 而不是 'innerHTML',因为 'innerHTML' 在 Internet Explorer 等旧版浏览器中存在一些已知问题。

通常,我不会进一步研究这个问题,只使用 document.createElement("option") 但我有两个问题:

  1. 我正在填充 2 个选择元素,每个元素有 190 个选项(总共 380 个),每个选项代表一个 ISO 语言代码。

    因此,通过 Array.prototype.forEach() 的每次迭代,Javscript 应用程序正在为每个 ISO 语言代码创建一个对象。内存中总共有 380 个对象。

    与仅仅构建一个非常大的选项字符串并通过'innerHTML'插入相比,document.createElement("option") 不是效率低下吗?

  2. 我已经在最新的 Chrome 和 Firefox 浏览器中测试了“innerHTML”方式,它运行良好。

    我无意支持 Internet Explorer 等旧版浏览器,所以在我的情况下,“innerHTML”是一个可行的选择吗?

我真的很想使用“innerHTML”,因为代码可读性更高(并且节省内存?):

Array.prototype.map().toString 给了我完整的选项字符串。

对此事的任何想法将不胜感激。

【问题讨论】:

  • 190 个选项有点多。让我想知道是否会出现可用性问题。
  • 我有一个笔记本,它的规格非常强大,它在两种方式下运行都非常流畅:document.createElement("option") 和 innerHTML 两者在客户端性能上都没有明显差异。
  • 这就是我的观点。虽然两者之间的性能可能存在差异,但大多数人不会注意到它。由于您无论如何都不会支持需要一个的平台,所以这是一个有争议的问题。你最好把时间花在可能真正引起注意的事情上,比如必须滚动浏览 190 个选项,而不是像这样过早优化。
  • 如果性能变化对用户的工作效率没有影响,那么它的好坏无关紧要。试图修复一些不相关的东西是过早的优化。你最好把时间花在其他事情上。
  • 这里的正确答案是不要使用带有 190 个选项的选择。让它成为一个自动完成或类似的字段,否则它是一个可用性噩梦。

标签: javascript dom


【解决方案1】:

正如@Tibrogargan 正确指出的那样,在尝试优化之前,您应该在要支持的最慢的设备上进行测试。在笔记本电脑上,10,000 个选项在 15 毫秒内处理,如果您关心资源非常有限的设备,可以说您应该将其作为 HTML 页面的一部分而不是运行 JS...

比较构建 DOM 和创建字符串来设置 innerHTML,我认为 DOM 的方式并不比 innerHTML 更差,甚至可能更好:

  • 创建的对象数量: document.createElement("option")(或new Option())创建DOM节点,当你设置innerHTML时也会创建这些节点!您可能会争辩说,这也会创建 DOM 对象的不必要的 JavaScript 包装器/表示,但使用 innerHTML 您会创建大量临时字符串,并且不清楚哪个更糟。
  • 可读性:使用new Option(label, value) 可以说比连接HTML 字符串("<option value='" + value + "'>" + ...) 更清晰,但如果你使用template literals,我会说这两种方法是相当的。
  • 众所周知,基准测试很难正确执行,但由于人们喜欢发布 jsperf 链接,here's one 显示 new Option() 在 Firefox 中更快(并且在 Chrome 中具有相同的性能)。我不会声称它是正确的(尤其是我对 GC 有疑问),但其他基准也没有声称 innerHTML 更快。

但如果有一个真实的测试用例,我敢于让你找到一个显示任何可测量差异的设备:

const labels = [...Array(1000).keys()].map((i) => Math.sin(i+1).toString(36).substring(2)); // random looking strings
const div = document.getElementById("container");


function timeIt(fn) {
    let start = performance.now();

    fn();

    let elapsedMS = performance.now() - start
    div.innerHTML = "";
    return elapsedMS;
}

function createUsingDOM() {
    let select = document.createElement("select");
    for (let i = 0, len = labels.length; i < len; i++) {
        select.appendChild(new Option(labels[i], i));
    }
    div.appendChild(select);
}

function createUsingInnerHTML() {
    let options = [];
    for (let i = 0, len = labels.length; i < len; i++) {
       options.push("<option value='" + i + "'>" + labels[i] + "</option>");
    }
    div.innerHTML = "<select>" + options.join("") + "</select>";
}

//createUsingDOM()
// createUsingInnerHTML();
alert(`DOM: ${timeIt(createUsingDOM)}ms, innerHTML: ${timeIt(createUsingInnerHTML)}ms`)
&lt;div id="container"&gt;&lt;/div&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-05
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多