Я занимаюсь рефакторингом некоторого старого кода JavaScript, и происходит множество манипуляций с DOM.
var d = document;
var odv = d.createElement("div");
odv.style.display = "none";
this.OuterDiv = odv;
var t = d.createElement("table");
t.cellSpacing = 0;
t.className = "text";
odv.appendChild(t);
Я хотел бы знать, есть ли лучший способ сделать это с помощью jQuery. Я экспериментировал с:
var odv = $.create("div");
$.append(odv);
// And many more
Но я не уверен, что это лучше.
Возможный дубликат Создание элемента div в jQuery
Uncaught TypeError: $ .create не является функцией



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Простое предоставление HTML элементов, которые вы хотите добавить в конструктор jQuery, $() вернет объект jQuery из недавно созданного HTML, подходящий для добавления в DOM с помощью метода jQuery append().
Например:
var t = $("<table cellspacing='0' class='text'></table>");
$.append(t);
Затем вы можете программно заполнить эту таблицу, если хотите.
Это дает вам возможность указать любой произвольный HTML-код, который вам нравится, включая имена классов или другие атрибуты, которые вы можете найти более краткими, чем использование createElement, а затем установить такие атрибуты, как cellSpacing и className, через JS.
Возможно, это было очевидно и указано в вашем примере, но создание элемента JQuery DOM с использованием синтаксиса $ ("<html string>") не может быть добавлено в DOM с помощью собственного метода <element> .appendChild или аналогичного. Вы должны использовать метод добавления jQuery.
$(htmlStr) реализован как document.createElement("div").innerHTML = htmlStr. Другими словами, он вызывает анализатор HTML браузера. В IE и в других браузерах искаженный HTML-код ломается по-разному.
Объект @Adam jQuery имеет функцию get, которая возвращает собственный элемент DOM. (Я знаю, что эта тема старая, но добавляю ее для справки. ;-))
Если у вас возникли проблемы со строкой html, попробуйте проанализировать ее с помощью jQuery.parseHTML
@Adam Или, если это проще для вашего потока кода / глаз, вы можете сделать [dom element].appendChild($('<html>')[0]);
Вот ваш пример в строке «один».
this.$OuterDiv = $('<div></div>')
.hide()
.append($('<table></table>')
.attr({ cellSpacing : 0 })
.addClass("text")
)
;
Обновлять: Я подумал, что обновлю этот пост, так как он все еще получает довольно много трафика. В комментариях ниже есть некоторые дискуссии о $("<div>"), $("<div></div>") и $(document.createElement('div')) как о способе создания новых элементов, который является «лучшим».
Я собрал небольшой ориентир, и вот примерно результаты повторения вышеуказанных опций 100000 раз:
jQuery 1.4, 1.5, 1.6
Chrome 11 Firefox 4 IE9
<div> 440ms 640ms 460ms
<div></div> 420ms 650ms 480ms
createElement 100ms 180ms 300ms
jQuery 1.3
Chrome 11
<div> 770ms
<div></div> 3800ms
createElement 100ms
jQuery 1.2
Chrome 11
<div> 3500ms
<div></div> 3500ms
createElement 100ms
Думаю, это не удивительно, но document.createElement - самый быстрый метод. Конечно, прежде чем приступить к рефакторингу всей кодовой базы, помните, что различия, о которых мы говорим здесь (во всех версиях jQuery, кроме архаичных), равняются примерно дополнительным 3 миллисекундам на тысячу элементов.
Обновление 2
Обновлен для jQuery 1.7.2 и поставлен тест на JSBen.ch, который, вероятно, немного более научен, чем мои примитивные тесты, плюс его можно использовать сейчас!
Вы обнаружите, что document.createElement намного быстрее, чем если бы jQuery преобразовал вашу строку html в элемент. (на всякий случай, если у вас есть желание сделать вещи более эффективными)
Это верно для jQuery <1.3. Теперь я верю, что это эквивалент скорости.
@Kevin, это правда, однако он заставляет jQuery выполнять больше работы (он запускает его через регулярное выражение для добавления закрывающего тега), поэтому я предпочитаю метод, описанный выше. Кроме того, он отличает ваш код от $('div'), который визуально очень похож, но функционально отличается.
Итак, в основном комбинация @Sungendran и @nickf будет $(document.createElement('div')), и она должна быть самой быстрой?
@Kolky: Лично я бы предпочел отказаться от увеличения скорости ~ 0,0001 с, чтобы иметь поддерживаемый и простой для чтения код.
Также помните, что jQuery будет генерировать теги элементов, которые экспортируются в верхнем регистре: stackoverflow.com/questions/2510702/…
document.createElement ('div') значит для меня больше, чем $ ('<div> </div>')
Я думаю, что «правильный» способ - это $ ('<div />'), при этом IMO имеет еще большее «значение», поскольку довольно очевидно, что вы создаете Node. Плохо то, что таким образом нарушается подсветка синтаксиса во всех редакторах = (
@Erik: не нарушает подсветку синтаксиса в Vim.
@Erik: Не нарушает подсветку синтаксиса в Emacs.
Просто для удовольствия: jsperf.com/divtester-jquery-vs-create-element Похоже, что jQuery позволит вам делать это 100 000 раз в секунду, по сравнению с 180 000 с createElement. Дополнительным преимуществом для меня является то, что у меня есть новый элемент jQuery, а не просто div. Итак, jQuery> createElement для меня.
@ себя, похоже, что его запуск чаще дает разные результаты. createElement работает намного лучше. Так что это действительно зависит от вашего варианта использования.
@self снова createElement работает намного лучше. Так что это действительно зависит от вашего варианта использования. Также я обновил код, чтобы он содержал все 3 предложенных метода, из которых я думаю, что jQuery (document.createElement ('div')) является лучшим для большинства ситуаций, когда вы получаете как элемент jQuery, так и часть производительности createElement.
@Mosselman: да, это то, о чем идет речь, поскольку $('<div></div>') функционально эквивалентен $(document.createElement('div')), но не document.createElement('div')
@nickf Я знаю, я просто хотел поделиться ссылкой на jsperf, которую я создал для тестирования. Знаю, что ничего нового в разговор не добавил. Просто увлекся этим. Если вы перейдете к jsperf.com/divtester-jquery-vs-create-element/2, вы увидите другую альтернативу, которую я нашел с помощью cloneNode (). Но это не быстрее.
@nickf Мне было интересно, можете ли вы обновить этот список до версии 1.7.2, может быть, были какие-то улучшения? (я ничего не знаю, но список будет обновляться)
@nickf Потрясающе, все равно такие же результаты, позор :(
Для лучшего x-браузера попробуйте сначала создать весь HTML как строку, затем innerHTML во фрагмент документа, а затем добавить его.
Я сократил document.createElement и создал плагин jQuery, чтобы добиться этого, и сохранил все функции jQuery, DOM и т. д. github.com/zlomerovic/jquery-create
@ErikEscobedo Не нарушает подсветку синтаксиса в VS 2010.
Кроссбраузерное примечание относительно обсуждения <div> и <div></div>: если вы создаете элементы HTML5 и поддерживаете IE8 (или ниже, я уверен), вы / должны / включать конечный тег ($('<header></header>')), или IE8 молча откажется добавлять его, даже с html5shim. Я не проверял, работает ли он с <header />.
Этот тест на апворк ... так что же лучше всего? Это, $ .append (t) или $ ('<div />')?
В моем случае потребовалось 16 строк javascript по сравнению с 2 строками jquery.
Возникла проблема с использованием $("<div>") в версии Opera45 для Linux: выдает консольную ошибку, утверждая, что отсутствует закрывающий тег. В других браузерах и SO все работало нормально. Тег быстрого закрытия ($("<div />")) решил проблему, но для обеспечения наилучшей кроссплатформенной совместимости рекомендуется придерживаться способа $("<div></div>") (как указано в документации jQuery). На мой взгляд, $(document.createElement('div')) - самый элегантный способ создания единого элемента.
fwiw, если вы создаете несколько элементов, var test = document.createElement('span'); $(test); работает немного быстрее. Конечно, самый быстрый вариант - полностью пропустить jQuery. Обновлено JSBench с обоими
jQuery из коробки не имеет эквивалента createElement. Фактически, большая часть работы jQuery выполняется внутри компании с использованием innerHTML, а не чистых манипуляций с DOM. Как упоминал выше Адам, именно так можно добиться аналогичных результатов.
Также доступны плагины, которые используют DOM поверх innerHTML, такие как appendDOM, DOMEC и FlyDOM, и это лишь некоторые из них. С точки зрения производительности собственный jquery по-прежнему является самым производительным (в основном потому, что он использует innerHTML)
Вы должны быть в курсе. jQuery не использует innerHtml, но анализирует строку HTML и внутренне строит дерево DOM с помощью document.createElement (). Это ядро jQuery.
Все довольно просто! Вот пара быстрых примеров ...
var $example = $( XMLDocRoot );
var $element = $( $example[0].createElement('tag') );
// Note the [0], which is the root
$element.attr({
id: '1',
hello: 'world'
});
var $example.find('parent > child').append( $element );
Создание новых элементов DOM - это основная функция метода jQuery(), см.:
Спасибо за ссылку на документ! $('<a>') неприемлем!
var mydiv = $('<div />') // also works
var div = $('<div/>');
div.append('Hello World!');
Самый короткий / простой способ создать элемент DIV в jQuery.
Я так делаю:
$('<div/>',{
text: 'Div text',
class: 'className'
}).appendTo('#parentDiv');
начиная с jQuery1.8, использование $.parseHTML() для создания элементов является лучшим выбором.
есть два преимущества:
1. если вы используете старый способ, который может быть чем-то вроде $(string), jQuery проверит строку, чтобы убедиться, что вы хотите выбрать тег html или создать новый элемент. Используя $.parseHTML(), вы явно указываете jQuery, что хотите создать новый элемент, поэтому производительность может быть немного лучше.
2. гораздо важнее то, что вы можете пострадать от межсайтовой атаки (больше информации), если будете использовать старый способ. если у вас есть что-то вроде:
var userInput = window.prompt("please enter selector");
$(userInput).hide();
плохой парень может ввести <script src = "xss-attach.js"></script>, чтобы подразнить вас. к счастью, $.parseHTML() избежал для вас этого затруднения:
var a = $('<div>')
// a is [<div></div>]
var b = $.parseHTML('<div>')
// b is [<div></div>]
$('<script src = "xss-attach.js"></script>')
// jQuery returns [<script src="xss-attach.js"></script>]
$.parseHTML('<script src = "xss-attach.js"></script>')
// jQuery returns []
Однако обратите внимание, что a - это объект jQuery, а b - это элемент html:
a.html('123')
// [<div>123</div>]
b.html('123')
// TypeError: Object [object HTMLDivElement] has no method 'html'
$(b).html('123')
// [<div>123</div>]
«Лучший выбор» вместо «создать [любой] элемент» может быть сильным. Ответ @ siergiej хорошо справляется, говоря, что parseHTML хорош для html, поступающего из внешних источников, но это "все ускорение исчезло после упаковки результатов в новый объект jQuery". То есть, если вы хотите жестко запрограммировать создание нового html-элемента, обернутого jQuery, стиль $("<div>stuff</div>"), похоже, все равно победит.
ОБНОВИТЬ
В последних версиях jQuery следующий метод не назначает свойства, переданные во втором объекте.
Предыдущий ответ
Я чувствую, что использовать document.createElement('div') вместе с jQuery быстрее:
$(document.createElement('div'), {
text: 'Div text',
'class': 'className'
}).appendTo('#parentDiv');
Я только что сделал для этого небольшой плагин jQuery: https://github.com/ern0/jquery.create
Он следует вашему синтаксису:
var myDiv = $.create("div");
В качестве второго параметра можно указать идентификатор узла DOM:
var secondItem = $.create("div","item2");
Это серьезно? Нет. Но этот синтаксис лучше, чем $ ("<div> </div>"), и это очень хорошее соотношение цены и качества.
Я новый пользователь jQuery, перехожу с DOMAssistant, который имеет аналогичную функцию: http://www.domassistant.com/documentation/DOMAssistantContent-module.php
Мой плагин проще, я думаю, что атрибуты и контент лучше добавлять методами цепочки:
$("#container").append( $.create("div").addClass("box").html("Hello, world!") );
Также это хороший пример простого jQuery-плагина (сотого).
Хотя это очень старый вопрос, я подумал, что было бы неплохо обновить его последней информацией;
Начиная с jQuery 1.8 существует функция jQuery.parseHTML (), которая теперь является предпочтительным способом создания элементов. Кроме того, есть некоторые проблемы с синтаксическим анализом HTML через $('(html code goes here)'), например, официальный сайт jQuery упоминает следующее в одна из их примечаний к выпуску:
Relaxed HTML parsing: You can once again have leading spaces or newlines before tags in $(htmlString). We still strongly advise that you use $.parseHTML() when parsing HTML obtained from external sources, and may be making further changes to HTML parsing in the future.
Чтобы иметь отношение к фактическому вопросу, приведенный пример можно перевести на:
this.$OuterDiv = $($.parseHTML('<div></div>'))
.hide()
.append($($.parseHTML('<table></table>'))
.attr({ cellSpacing : 0 })
.addClass("text")
)
;
что, к сожалению, менее удобно, чем использование только $(), но дает вам больше контроля, например, вы можете исключить теги скрипта (хотя он оставит встроенные скрипты, такие как onclick):
> $.parseHTML('<div onclick = "a"></div><script></script>')
[<div onclick="a"></div>]
> $.parseHTML('<div onclick = "a"></div><script></script>', document, true)
[<div onclick="a"></div>, <script></script>]
Кроме того, вот эталон из верхнего ответа, адаптированный к новой реальности:
jQuery 1.9.1
$.parseHTML: 88ms $($.parseHTML): 240ms <div></div>: 138ms <div>: 143ms createElement: 64ms
Похоже, что parseHTML намного ближе к createElement, чем $(), но все ускорение пропало после переноса результатов в новый объект jQuery.
Не упоминается в предыдущих ответах, поэтому я добавляю рабочий пример того, как создавать элементы элементов с помощью последней версии jQuery, а также с дополнительными атрибутами, такими как контент, класс или обратный вызов onclick:
const mountpoint = 'https://jsonplaceholder.typicode.com/users'
const $button = $('button')
const $tbody = $('tbody')
const loadAndRender = () => {
$.getJSON(mountpoint).then(data => {
$.each(data, (index, { id, username, name, email }) => {
let row = $('<tr>')
.append($('<td>', { text: id }))
.append($('<td>', {
text: username,
class: 'click-me',
on: {
click: _ => {
console.info(name)
}
}
}))
.append($('<td>', { text: email }))
$tbody.append(row)
})
})
}
$button.on('click', loadAndRender).click-me {
background-color: lightgrey
}<table style = "width: 100%">
<thead>
<tr>
<th>ID</th>
<th>Username</th>
<th>Email</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<button>Load and render</button>
<script src = "https://code.jquery.com/jquery-3.3.1.min.js"></script>Как насчет этого, например, если вы хотите добавить элемент <option> внутри <select>
$('<option/>')
.val(optionVal)
.text('some option')
.appendTo('#mySelect')
Очевидно, вы можете применить к любому элементу
$('<div/>')
.css('border-color', red)
.text('some text')
.appendTo('#parentDiv')