Вопрос

У меня появилось плохое предчувствие по поводу того, как я вставляю большие объемы HTML.Давайте предположим, что мы получили:

var html="<table>..<a-lot-of-other-tags />..</table>"

и я хочу вложить это в

$("#mydiv")

раньше я делал что-то вроде

var html_obj = $(html); $("#mydiv").append(html_obj);

Правильно ли, что jQuery выполняет синтаксический анализ html для создания DOM-объектов?Ну, это то, что я где-то читал (ОБНОВЛЕНИЕ: Я имел в виду, что я читал, jQuery анализирует html для создания всего DOM-дерева вручную - это бессмыслица, не так ли?!), поэтому я изменил свой код:

$("#mydiv").attr("innerHTML", $("#mydiv").attr("innerHTML") + html);

По ощущениям быстрее, не так ли?И правильно ли, что это эквивалентно:

document.getElementById("mydiv").innerHTML += html ?или jquery делает какие-то дополнительные дорогостоящие вещи в фоновом режиме?

Хотелось бы также изучить альтернативные варианты.

Это было полезно?

Решение

innerHTML работает удивительно быстро, и во многих случаях вы получите наилучшие результаты, просто установив это (я бы просто использовал append).

Однако, если в "mydiv" уже много чего есть, вы заставляете браузер снова анализировать и отображать весь этот контент (все, что было там раньше, плюс весь ваш новый контент). Вы можете избежать этого, добавив вместо этого фрагмент документа в "mydiv":

var frag = document.createDocumentFragment();
frag.innerHTML = html;
$("#mydiv").append(frag);

Таким образом, анализируется только ваш новый контент (это неизбежно), а существующий контент - нет.

Редактировать:Я виноват...Я обнаружил, что innerHTML недостаточно хорошо поддерживается во фрагментах документа.Вы можете использовать тот же метод с любым типом узла.Для вашего примера вы могли бы создать узел корневой таблицы и вставить в него innerHTML:

var frag = document.createElement('table');
frag.innerHTML = tableInnerHtml;
$("#mydiv").append(frag);

Другие советы

Попробуйте следующее:

$("#mydiv").append(html);

Другими ответами, включая принятый ответ, являются медленнее Автор: 2-10x: jsperf.

Принятый ответ не работает в Т.е. 6, 7 и 8 потому что вы не можете установить innerHTML из a <table> элемент, из-за ошибки в IE: jsbin.

Чего вы пытаетесь избежать?"Плохое предчувствие" - это невероятно расплывчато.Если вы услышали "DOM работает медленно" и решили "избежать DOM", то это невозможно.Любой метод вставки кода на страницу, включая innerHTML, приведет к созданию объектов DOM.DOM - это представление документа в памяти вашего браузера.Ты хотеть Объекты DOM, которые необходимо создать.

Причина, по которой люди говорят "DOM работает медленно", заключается в том, что создание элементов с document.createElement(), который является официальным интерфейсом DOM для создания элементов, работает медленнее, чем использование нестандартного свойства innerHTML в некоторых браузерах.Это не означает, что создавать DOM-объекты плохо, это необходимый создавать объекты DOM, иначе ваш код вообще ничего бы не делал.

Ответ об использовании фрагмента DOM находится на правильном пути.Если у вас есть куча html-объектов, которые вы постоянно вставляете в DOM, то вы увидите некоторые улучшения скорости использования фрагмента.Этот пост Джона Ресига объясняет это довольно хорошо:http://ejohn.org/blog/dom-documentfragments/

Самый быстрый способ добавления элементов

Самый быстрый способ добавить к дереву DOM - это поместить все ваши добавления в буфер в одном фрагменте DOM, а затем добавить фрагмент dom к dom.

Это метод, который я использую в своем игровом движке.

//Returns a new Buffer object
function Buffer() {

    //the framgment
    var domFragment = document.createDocumentFragment();

    //Adds a node to the dom fragment
    function add(node) {
        domFragment.appendChild(node);
    }

    //Flushes the buffer to a node
    function flush(targetNode) {

        //if the target node is not given then use the body
        var targetNode = targetNode || document.body;

        //append the domFragment to the target
        targetNode.appendChild(domFragment);

    }

    //return the buffer
    return {
        "add": add,
        "flush": flush
    }
}


//to make a buffer do this
var buffer = Buffer();

//to add elements to the buffer do the following
buffer.add(someNode1);

//continue to add elements to the buffer
buffer.add(someNode2);
buffer.add(someNode3);
buffer.add(someNode4);
buffer.add(someN...);

//when you are done adding nodes flush the nodes to the containing div in the dom
buffer.flush(myContainerNode);

Используя этот объект, я могу отображать ~ 1000 элементов на экране ~ 40 раз в секунду в firefox 4.

Вот пример использования.

Для начала напишите сценарий, умножающий время, необходимое для выполнения этого действия, на 100 или 1000 раз с каждым методом.

Чтобы убедиться, что повторы каким-то образом не оптимизированы - я не эксперт в движках JavaScript - меняйте html, который вы вставляете каждый раз, скажем, помещая '0001', затем '0002', затем '0003' в определенную ячейку таблицы.

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

Вы упомянули, что вас интересуют альтернативы.Если вы посмотрите на список Плагины jQuery, связанные с DOM вы найдете несколько, предназначенных для программной генерации DOM-деревьев.Смотрите, например Суперфлайдом или Создатель элементов DOM;но есть и другие.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top