将元素存储在内存中以防止过于频繁地更新DOM

Storing elements in memory to prevent updating the DOM too often?

本文关键字:于频繁 DOM 更新 存储 元素 内存      更新时间:2023-09-26

目前我有一个循环,在每次迭代更新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++;
            }
        }
    }

在循环中处理DOM元素是很慢的—无论是否将它们附加到文档中。在最后附加它们要快一点,因为只需要重新绘制,但仍然很慢。

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

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

你的方法是足够好的,除非你有很多项目添加到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("");

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

你的代码太臃肿了,DOM 0方法会更快。

如果速度真的很重要,存储spot + batchSize &&我& lt;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++;
        }
    }
}