JQuery: самая быстрая вставка DOM? - PullRequest
21 голосов
/ 23 сентября 2008

У меня плохое предчувствие, что я вставляю большие объемы 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 делает некоторые дополнительные дорогие вещи в фоновом режиме?

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

Ответы [ 8 ]

32 голосов
/ 12 декабря 2010

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

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

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

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

22 голосов
/ 23 сентября 2008

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);
9 голосов
/ 23 сентября 2008

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

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

2 голосов
/ 10 июня 2011

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

Самый быстрый способ добавления к дереву 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.

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

2 голосов
/ 27 сентября 2008

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

1 голос
/ 23 сентября 2008

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

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

0 голосов
/ 28 августа 2012

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

0 голосов
/ 23 сентября 2008

Вы упоминаете, что интересовались альтернативами. Если вы посмотрите на список связанных с DOM плагинов jQuery , вы найдете несколько, которые предназначены для программной генерации DOM-деревьев. Например, SuperFlyDom или DOM Elements Creator ; но есть и другие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...