Каков наиболее эффективный способ создания элементов HTML с использованием jQuery? - PullRequest
417 голосов
/ 29 ноября 2008

В последнее время я делал много модальных всплывающих окон, а что нет, для которых я использовал jQuery. Метод, который я использовал для создания новых элементов на странице, в подавляющем большинстве случаев был следующим:

$("<div></div>");

Однако мне кажется, что это не самый лучший или самый эффективный способ сделать это. Каков наилучший способ создания элементов в jQuery с точки зрения производительности?

В этом ответе приведены критерии для приведенных ниже предложений.

Ответы [ 12 ]

304 голосов
/ 29 ноября 2008

Я использую $(document.createElement('div')); Бенчмаркинг-шоу эта техника самая быстрая. Я предполагаю, что это потому, что jQuery не должен идентифицировать его как элемент и создать сам элемент.

Вы должны действительно запустить тесты с различными движками Javascript и взвесить аудиторию с результатами. Примите решение оттуда.

163 голосов
/ 29 ноября 2008

лично я бы предложил (для удобства чтения):

$('<div>');

некоторые цифры на данный момент (safari 3.2.1 / mac os x):

var it = 50000;

var start = new Date().getTime();
for (i = 0; i < it; ++i)  {
  // test creation of an element 
  // see below statements
}
var end = new Date().getTime();
alert( end - start );                

var e = $( document.createElement('div') );  // ~300ms
var e = $('<div>');                          // ~3100ms
var e = $('<div></div>');                    // ~3200ms
var e = $('<div/>');                         // ~3500ms              
152 голосов
/ 14 октября 2013

Вопрос:

Какой самый эффективный способ создания HTML-элементов с использованием jQuery?

Ответ:

Поскольку речь идет о jQuery, тогда я думаю, что лучше использовать этот (чистый) подход (вы используете)

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'text':'Text Only',
}).on('click', function(){
    alert(this.id); // myDiv
}).appendTo('body');

DEMO.

Таким образом, вы даже можете использовать обработчики событий для определенного элемента, например

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'style':'cursor:pointer;font-weight:bold;',
    'html':'<span>For HTML</span>',
    'click':function(){ alert(this.id) },
    'mouseenter':function(){ $(this).css('color', 'red'); },
    'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');

DEMO.

Но когда вы имеете дело с большим количеством динамических элементов, вам следует избегать добавления события handlers в конкретный элемент, вместо этого вы должны использовать делегированный обработчик события, такой как

$(document).on('click', '.myClass', function(){
    alert(this.innerHTML);
});

var i=1;
for(;i<=200;i++){
    $('<div/>', {
        'class':'myClass',
        'html':'<span>Element'+i+'</span>'
    }).appendTo('body');
}

DEMO.

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

Обновление: Поскольку мы можем использовать следующий подход для создания динамического элемента

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    'size': '30'
}).appendTo("body");

Но атрибут size нельзя установить с помощью этого подхода с использованием jQuery-1.8.0 или более поздней версии, а вот старый отчет об ошибке , посмотрите на в этом примере с использованием jQuery-1.7.2 который показывает, что атрибут size установлен на 30 с использованием приведенного выше примера, но с использованием того же подхода мы не можем установить атрибут size с помощью jQuery-1.8.3, здесь нерабочая скрипка . Итак, чтобы установить атрибут size, мы можем использовать следующий подход

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    attr: { size: "30" }
}).appendTo("body");

Или этот

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    prop: { size: "30" }
}).appendTo("body");

Мы можем передать attr/prop как дочерний объект, но он работает в jQuery-1.8.0 and later версиях проверки в этом примере , но он не будет работать в jQuery-1.7.2 or earlier (не тестировался в все более ранние версии).

Кстати, взято из jQuery сообщение об ошибке

Есть несколько решений. Во-первых, не использовать его вообще, так как это не экономит ваше место, и это улучшает ясность код:

Они посоветовали использовать следующий подход ( работает и в более ранних , протестировано в 1.6.4)

$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");

Итак, этот подход лучше использовать, ИМО. Это обновление сделано после того, как я прочитал / нашел этот ответ и в этом ответе показано, что если вы используете 'Size'(capital S) вместо 'size', тогда оно будет просто нормально работать , даже в version-2.0.2

$('<input>', {
    'type' : 'text',
    'Size' : '50', // size won't work
    'autofocus' : 'true'
}).appendTo('body');

Также читайте о prop , потому что есть разница, Attributes vs. Properties, она зависит от версии.

37 голосов
/ 25 апреля 2010

На самом деле, если вы делаете $('<div>'), jQuery также будет использовать document.createElement().

(Просто взгляните на строку 117 ).

Существуют некоторые издержки при вызове функции, но если производительность не критична (вы создаете сотни [тысяч] элементов), нет особых причин возвращаться к обычному DOM .

Просто создание элементов для новой веб-страницы - это, вероятно, тот случай, когда вам лучше всего придерживаться способа jQuery .

20 голосов
/ 05 февраля 2010

Это не правильный ответ на вопрос, но все же я хотел бы поделиться этим ...

Использование только document.createElement('div') и пропуск JQuery значительно улучшат производительность, когда вы захотите создать множество элементов на лету и добавить в DOM.

20 голосов
/ 29 ноября 2008

Если у вас много HTML-контента (больше, чем просто один div), вы можете подумать о том, чтобы встроить HTML-страницу в скрытый контейнер, затем обновить его и сделать его видимым при необходимости. Таким образом, большая часть вашей разметки может быть предварительно проанализирована браузером и избежать срыва JavaScript при вызове. Надеюсь, это поможет!

16 голосов
/ 29 ноября 2008

Я думаю, вы используете лучший метод, хотя вы можете оптимизировать его до:

 $("<div/>");
11 голосов
/ 29 ноября 2008

Вам не нужна необработанная производительность от операции, которую вы будете выполнять крайне редко с точки зрения ЦП.

9 голосов
/ 12 июля 2013

Вы должны понимать, что значение производительности создания элемента не имеет значения в первую очередь при использовании jQuery.

Имейте в виду, что нет реальной цели создания элемента, если вы на самом деле не собираетесь его использовать.

Вы можете испытать на себе что-то вроде теста $(document.createElement('div')) против $('<div>') и получить значительный прирост производительности от использования $(document.createElement('div')), но это всего лишь элемент, которого пока нет в DOM.

Однако, в конце концов, вы все равно захотите использовать элемент, поэтому реальный тест должен включать f.ex. .appendTo ();

Посмотрим, протестируем ли вы друг против друга следующее:

var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');

Вы заметите, что результаты будут отличаться. Иногда один способ лучше, чем другой. И это только потому, что количество фоновых задач на вашем компьютере со временем меняется.

Проверьте себя здесь

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

8 голосов
/ 22 января 2012

Кто-то уже сделал тест: jQuery document.createElement эквивалент?

$(document.createElement('div')) - большой победитель.

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