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

426

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

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

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

Этот ответ имеет ориентиры для предложений ниже.

Darko Z
источник
1
Поэкспериментируйте с удалением стилей и посмотрите, ускоряет ли это процесс. Я считаю, что CSS-приложения и обновления больше всего меня замедляют на больших страницах.
CVertex
3
Остерегайтесь преждевременной оптимизации - если вы не делаете это для сотен элементов DOM одновременно или используете ОЧЕНЬ старые браузеры, то вы, вероятно, не заметите никакой разницы в производительности браузера.
Blazemonger
1
@Blazemonger Не так уж много, что мне нужен был более эффективный метод создания элементов DOM, но ситуация, в которой я находился, заставила меня задуматься о том, какие есть альтернативы и насколько эффективными они могут быть.
Дарко Z
2
jQuery - это библиотека - по этой причине вы почти всегда будете нести накладные расходы на производительность: это все равно, что разговаривать с кем-то через переводчика. Если вы не хотите использовать сырой JavaScript, воспользуйтесь тем, как быстро вы пишете $ ('<div>') и принимаете снижение производительности.
Дэнни Буллис
1
jsben.ch/#/bgvCV <= этот тест должен ответить на ваш вопрос
EscapeNetscape

Ответы:

308

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

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

strager
источник
16
jQuery «добавляет» его в DOM? Куда? Это не имеет большого смысла для меня - куда делись div?
Страгер
28
созданный div в jquery должен быть добавлен так же, как в javascript. $ ('<div>') сам по себе не присоединен к DOM, пока вы не добавите его к чему-либо.
Оуэн
6
@ Дэвид - очевидно, ты прав. Отмечу, что я добавил комментарий около 2 лет назад, когда я только начинал изучать jQuery. Вам нужно будет сделать appendTo... Поскольку комментарии были явно неправильными, я удалил их.
tvanfosson
16
Ссылка на бенчмаркинг великолепна, но она также тестирует создание десятков тысяч элементов. Когда вы когда-нибудь будете иметь дело с таким количеством элементов в типичной ситуации? Скорее всего, вам нужно беспокоиться о большем, чем о том, как создать элемент. document.createElement "Выполнено 39 682 раза за 0,097 секунды", тогда как $ ('<div>') "Выполнено 12 642 за 0,068 секунды." Я бы сказал, что если что-то может работать тысячи раз менее чем за секунду, вы в безопасности.
Дэнни Буллис
20
Кроме того, используя $ (document.createElement ('div')); Я бы сказал, что он менее эффективен, потому что для написания достаточно небольшой суммы выгоды, которую вы получите в браузере, потребуется больше времени, если вы будете создавать только один элемент за раз здесь и там. Технически, jQuery сам по себе менее эффективен в качестве библиотеки из-за затрат на поиск и из-за накладных расходов, которые вы несете при его использовании. Если кто-то так хочет сохранить драгоценные тысячные доли миллисекунды, используя document.createElement вместо $ ('<div>'), то он не должен использовать jQuery:], потому что $ ('<div>') это одна из причин, почему вы используете его!
Дэнни Буллис
163

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

$('<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              
Оуэн
источник
15
Из документации jquery: «При создании отдельных элементов используйте закрывающий тег или формат XHTML. Например, чтобы создать диапазон, используйте $ ("<span />") или $ ("<span> </ span>") вместо закрывающей косой черты / тега. '
tvanfosson
6
@ Оуэн, это поведение - ошибка, а не особенность. Мусор, мусор - это просто так, что мусор, который вы получаете, является приемлемым. Не полагайтесь на это между версиями jQuery, если только спецификация для функции не изменится.
Страгер
2
Как и ожидалось, мы увидим похожие цифры в Mac OS X Chrome (100 мс для createElement () и 500 мс при разборе текста) и Mac OS X Firefox (350 мс против 1000 мс). Спасибо, что написали тестовый цикл.
Анника Бэкстрем
3
@tvanfosson Это изменилось, по-видимому, в текущих документах говорится: «Когда параметр имеет один тег (с необязательным закрывающим тегом или быстрым закрытием) - $ (" <img /> ") или $ (" <img> " ), $ ("<a> </a>") или $ ("<a>") - jQuery создает элемент с помощью встроенной функции JavaScript createElement (). "
Метатрон
3
@MarcStober Без обид. Это все еще здесь: http://api.jquery.com/jQuery/#jQuery2 . В документах упоминается необязательный закрывающий тег или быстрое закрытие
metatron
155

Вопрос:

Каков наиболее эффективный способ создания элементов 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');

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

Альфа
источник
Что это за синтаксис $ ('<div />', {.........}), я его искал и нашел похожее, используя $ ('<div>). Attr ( {......})?
Рафаэль Руис Табарес
@RafaelRuizTabares, $('<div>', {...})вы передаете объект, который содержит все атрибуты, и $('<div>').attr({...})вы создаете элемент без каких-либо атрибутов, но устанавливаете атрибуты, используя attr()метод позже.
Альфа
@TheAlpha, где я могу найти информацию о том, что я могу написать внутри {}? Потому что я вижу, что они являются атрибутами и событиями, но для <div> вы тоже используете html. Спасибо!
Рафаэль Руис Табарес
Поиск по jQuery.comсайту может быть полезен @RafaelRuizTabares, или Google его :-)
Альфа
2
Это, безусловно, самый чистый и читаемый способ! Вероятно, не быстрый способ, но, конечно, меньше ошибок, склонных к добавлению строки. Спасибо @TheAlpha
Арес
37

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

(Просто посмотрите на строку 117 ).

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

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

Эдвин
источник
20

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

Коллин Аллен
источник
Спасибо за совет. Я использовал этот подход раньше, однако в данном конкретном случае я специально хочу узнать о создании элементов.
Дарко Z
20

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

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

Irshad
источник
16

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

 $("<div/>");
tvanfosson
источник
11

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

yfeldblum
источник
Зависит от того, как часто вы это делаете.
Рич Брэдшоу
8
ОП создает модальное всплывающее окно . Эта операция не повторяется тысячи раз в секунду. Вместо этого это повторяется, возможно, раз в несколько секунд, максимум. Использование jQuery(html :: String)метода совершенно нормально. Если ситуация не будет необычной, вряд ли кто-то достигнет лучшего восприятия . Потратьте энергию оптимизации на случаи, которые могли бы использовать его. Кроме того, JQuery оптимизирован для скорости во многих отношениях. Делайте с ним что-то вменяемое и доверяйте, но проверяйте, что это быстро.
yfeldblum
9

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

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

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

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

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

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

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

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

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

Яни Хюйтяйнен
источник
Я знаю, что это старо, но в первом примере нет необходимости в jQuery:document.getElementById('target).appendChild(document.createElement('div'));
hisdrewness
7

Один момент заключается в том, что это может быть проще сделать:

$("<div class=foo id=bar style='color:white;bgcolor:blue;font-size:12pt'></div>")

Затем сделать все это с помощью вызовов jquery.

Товия
источник
3

Я использую jquery.min v2.0.3. Для меня лучше использовать следующее:

var select = jQuery("#selecter");
jQuery("`<option/>`",{value: someValue, text: someText}).appendTo(select);

следующим образом:

var select = jQuery("#selecter");
jQuery(document.createElement('option')).prop({value: someValue, text: someText}).appendTo(select);

Время обработки первого кода намного меньше, чем второго кода.

Марсель GJS
источник