1

目前我有一个循环在每次迭代中更新 DOM;我了解到这是一种不好的做法,您应该尽可能少地更新 DOM 以获得更好的速度。

所以我想知道如何编辑下面的内容,以便我可以将所有元素存储在一个元素或其他东西中,然后在循环结束后添加一个 DOM。

这是循环..

    for (var i = spot; i < spot + batchSize && i < cats.options.length; i++) {

        // Check if the cat is selected

        if (cats.options[i].selected == true) {

            // Set this category's values to some variables
            var cat_id = cats.options[i].getAttribute('value');
            var cat_name = cats.options[i].text;     

            if (checkCatSICAdd(cat_id) === false) {           

                // Now we create the new element
                var new_option = document.createElement('option');

                // Add attribute
                new_option.setAttribute('value',cat_id);

                // Create text node
                var new_text_node = document.createTextNode(cat_name);

                // Append new text node to new option element we created
                new_option.appendChild(new_text_node);

                // Append new option tag to select list
                sel_cats.appendChild(new_option);

            } else {
                failed++;
            }

        }

    }
4

6 回答 6

4

在循环中使用 DOM 元素很慢 - 无论您是否将它们附加到文档中。在最后附加它们会更快一些,因为只需要重绘,但它仍然很慢。

innerHTML正确的方法是生成一个包含 HTML 的普通旧字符串,并使用DOM 元素的属性将此字符串附加到DOM。

于 2011-04-04T21:35:30.077 回答
1

你的代码应该没问题。在 Javascript 完成执行之前,DOM 不会真正重绘。但是,如果您遇到了性能不佳的问题浏览器,您可以尝试select在尚未附加到 DOM 的循环之前创建一个新的,并像现在一样填充它,然后在最后替换sel_cats为新select的。这样,DOM 只更新一次。

于 2011-04-04T21:34:59.980 回答
1

除非您添加了很多项目,否则您的方式已经足够好了sel_cats——您只添加到 DOM 一次。

提高效率的唯一方法可能是将选项存储为原始 HTML,然后在循环后分配:

var arrHTML = [];
for (var i = spot; i < spot + batchSize && i < cats.options.length; i++) {
    // Check if the cat is selected
    if (cats.options[i].selected == true) {
        // Set this category's values to some variables
        var cat_id = cats.options[i].value;
        var cat_name = cats.options[i].text;     
        if (checkCatSICAdd(cat_id) === false) {           
            arrHTML.push("<option value=\"" + cat_id + "\">" + cat_name + "</option>";
        }
        else {
            failed++;
        }
    }
}
sel_cats.innerHTML = arrHTML.join("");
于 2011-04-04T21:37:39.420 回答
1

将选择列表分配给变量后,使用其父标记上的 removeChild 将其从 dom 中删除。然后,您可以在将选择列表添加回 dom 之前在循环中使用 appendChild。

于 2011-04-04T21:37:45.600 回答
1

您可能会从今天早些时候看到这个。

不确定它是否会有所帮助,但主题足够接近:-) 这是关于使用 documentFragment 或内存中元素将元素添加到内存中的 DOM 的讨论。

于 2011-04-04T21:46:55.307 回答
0

您的代码过于臃肿,DOM 0 方法会快得多。

如果速度真的很重要,请将 spot + batchSize && i < cats.options.length 存储在变量中,这样它们就不会在每个循环中重新计算(现代浏览器可能不会,但旧浏览器会):

for (var i=spot, j=spot+batchSize, k=cats.options.length; i < j && i < k; i++) {

    // Store reference to element
    var opt = cats.options[i];

    // The selected property is boolean, no need to compare
    if (opt.selected) {

        // if checkCatSICAdd() returns boolean, just use it
        // but maybe you need the boolean comparison
        if (checkCatSICAdd(opt.name) === false) {

            // Wrapped for posting
            sel_cats.options[sel_cats.options.length] = 
                                         new Option(opt.value, opt.name);

        } else {
            failed++;
        }
    }
}
于 2011-04-05T01:20:25.133 回答