Хранить элементы в памяти, чтобы предотвратить слишком частое обновление DOM? - PullRequest
1 голос
/ 05 апреля 2011

В настоящее время у меня есть цикл, который обновляет 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++;
            }

        }

    }

Ответы [ 6 ]

3 голосов
/ 05 апреля 2011

Работа с элементом DOM в цикле медленная - независимо от того, прикрепляете ли вы их к документу или нет.Присоединение их в конце немного быстрее, поскольку требуется только перерисовка, но все еще медленно.

Правильный способ - создать простую старую строку, содержащую HTML, и присоединить эту строку к DOM, используя свойство innerHTMLэлемента DOM.

1 голос
/ 05 апреля 2011

Вы могли бы взглянуть на это с более раннего сегодняшнего дня.

не уверен, поможет ли это, но тема достаточно близка :-) Это обсуждение о добавлении элементов в DOMв памяти с использованием documentFragment или элементов в памяти.

1 голос
/ 05 апреля 2011

Как только у вас есть список выбора, назначенный переменной, удалите его из dom, используя removeChild в его родительском теге. Затем вы можете использовать appendChild в цикле перед добавлением списка выбора обратно в dom.

1 голос
/ 05 апреля 2011

Ваш путь достаточно хорош, если к 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("");
1 голос
/ 05 апреля 2011

Ваш код должен быть в порядке.DOM на самом деле не будет перерисовываться, пока не завершится выполнение Javascript.Однако, если вы столкнулись с проблемой браузера, который работает плохо, вы можете попробовать создать новый select перед циклом, который еще не подключен к DOM, заполнив его таким, какой вы есть, затем заменив sel_cats этимновый select в конце.Таким образом, DOM обновляется только один раз.

0 голосов
/ 05 апреля 2011

Ваш код сильно раздут, методы DOM 0 будут намного быстрее.

Если скорость действительно имеет значение, сохраните spot + batchSize && i

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++;
        }
    }
}
...