Преимущества createElement над innerHTML?
на практике, каковы преимущества использования createElement над innerHTML? Я спрашиваю, потому что я убежден, что использование innerHTML более эффективно с точки зрения производительности и удобочитаемости/ремонтопригодности кода, но мои товарищи по команде решили использовать createElement в качестве подхода к кодированию. Я просто хочу понять, как createElement может быть более эффективным.
4 ответов:
есть несколько преимуществ использования
createElementвместо измененияinnerHTML(в отличие от того, чтобы просто выбросить то, что уже есть и заменить его) помимо безопасности, как уже упоминалось Пекка:сохраняет существующие ссылки на элементы DOM при добавлении элементов
когда вы добавляете (или иным образом изменяете)
innerHTML, все узлы DOM внутри этого элемента должны быть повторно проанализированы и воссозданы. Если вы сохранили какие-либо ссылки на узлы, они будут по существу бесполезно, потому что они больше не появляются.сохраняет обработчики событий, прикрепленные к любым элементам DOM
это действительно просто частный случай (хотя и общий) последнего. Установка
innerHTMLне будет автоматически присоединять обработчики событий к новым элементам, которые он создает, поэтому вам придется отслеживать их самостоятельно и добавлять их вручную. Делегирование событий может устранить эту проблему в некоторых случаях.может быть проще/быстрее в некоторых случаях
если вы делаете много дополнений, вы определенно не хотите продолжать сброс
innerHTMLпотому что, хотя и быстрее для простых изменений, многократный повторный разбор и создание элементов будет медленнее. Способ обойти это-создать HTML в строке и установитьinnerHTMLодин раз, когда вы закончите. В зависимости от ситуации, обработка строк может быть медленнее, чем просто создание элементов и их добавление.дополнительно, код обработки строк может быть более сложным (особенно если вы хотите, чтобы он был безопасным).
вот функцию я использую, иногда, что делает его более удобным в использовании
createElement.function isArray(a) { return Object.prototype.toString.call(a) === "[object Array]"; } function make(desc) { if (!isArray(desc)) { return make.call(this, Array.prototype.slice.call(arguments)); } var name = desc[0]; var attributes = desc[1]; var el = document.createElement(name); var start = 1; if (typeof attributes === "object" && attributes !== null && !isArray(attributes)) { for (var attr in attributes) { el[attr] = attributes[attr]; } start = 2; } for (var i = start; i < desc.length; i++) { if (isArray(desc[i])) { el.appendChild(make(desc[i])); } else { el.appendChild(document.createTextNode(desc[i])); } } return el; }если вы называете это так:
make(["p", "Here is a ", ["a", { href:"http://www.google.com/" }, "link"], "."]);вы получаете эквивалент этого HTML:
<p>Here is a <a href="http://www.google.com/">link</a>.</p>
пока
innerHTMLможет быть быстрее, я не согласен, что это лучше с точки зрения читаемости или обслуживания. Он может быть короче, чтобы положить все в одну строку, но более короткий код не всегда обязательно более ремонтопригодны.конкатенация строк просто не масштабируется, когда динамические элементы DOM должны быть созданы как плюс' и кавычки открытия и закрытия становится трудно отслеживать. Рассмотрим следующие примеры:
результирующий элемент div с двумя внутренними области, содержимое которых является динамическим. Одно из имен классов (воин) внутри первого пролета также является динамическим.
<div> <span class="person warrior">John Doe</span> <span class="time">30th May, 2010</span> </div>предположим, что следующие переменные уже определены:
var personClass = 'warrior'; var personName = 'John Doe'; var date = '30th May, 2010';используя только innerHTML и затирая все в одну строку, мы получаем:
someElement.innerHTML = "<div><span class='person " + personClass + "'>" + personName + "</span><span class='time'>" + date + "</span></div>";вышеуказанный беспорядок можно очистить с помощью замены строк, чтобы избежать открытия и закрытия строк каждый раз. Даже для простых текстовых замен я предпочитаю использовать о конкатенации строк.
это простая функция, которая принимает объект ключей и значений замены и заменяет их в строке. Он предполагает, что ключи имеют префикс
$для обозначения они имеют особое значение. Он не делает никаких побегов или обработки крайних случаев, где$появляется в значении замены и т. д.function replaceAll(string, map) { for(key in map) { string = string.replace("$" + key, map[key]); } return string; } var string = '<div><span class="person $type">$name</span><span class="time">$date</span></div>'; var html = replaceAll(string, { type: personClass, name: personName, date: date }); someElement.innerHTML = html;это можно улучшить, разделив атрибуты, текст и т. д. при построении объекта, чтобы получить больше программного управления над конструкцией элемента. Например, с помощью MooTools мы можем передать свойства объекта в виде карты. Это, безусловно, более ремонтопригодно, и я бы сказал, более читабельно. jQuery 1.4 использует аналогичный синтаксис для передачи карты для инициализации объектов DOM.
var div = new Element('div'); var person = new Element('span', { 'class': 'person ' + personClass, 'text': personName }); var when = new Element('span', { 'class': 'time', 'text': date }); div.adopt([person, when]);Я бы не назвал чистый подход DOM ниже, чтобы быть более читаемым, чем те, что выше, но это, безусловно, более ремонтопригодным, потому что нам не нужно отслеживать котировки открытия / закрытия и многочисленные плюсы знаки.
var div = document.createElement('div'); var person = document.createElement('span'); person.className = 'person ' + personClass; person.appendChild(document.createTextNode(personName)); var when = document.createElement('span'); when.className = 'date'; when.appendChild(document.createTextNode(date)); div.appendChild(person); div.appendChild(when);наиболее читаемая версия, скорее всего, будет результатом использования какой-то JavaScript templating.
<div id="personTemplate"> <span class="person <%= type %>"><%= name %></span> <span class="time"><%= date %></span> </div> var div = $("#personTemplate").create({ name: personName, type: personClass, date: date });
пользователей bobince ставит ряд минусов очень, очень хорошо в его критика jQuery.
... Кроме того, вы можете сделать div, сказав $("+message+") вместо того, чтобы возиться с документом.createElement ('div') и текстовые узлы. Ура! Только... Подожди. Вы не избежали этого HTML и, вероятно, только что создали дыру в безопасности межсайтового скриптинга, только на стороне клиента на этот раз. И после того, как вы потратили так много времени на очистку вашего PHP использовать функции htmlspecialchars на стороне сервера тоже. Какой позор. Ну, никто не заботится о правильности или безопасности, не так ли?
jQuery не полностью виноват в этом. В конце концов, свойство innerHTML существует уже много лет и уже оказалось более популярным, чем DOM. Но библиотека, безусловно, поощряет этот стиль кодирования.
что касается производительности:
InnerHTML, безусловно, будет медленнее, потому что он должен быть проанализирован и внутренне преобразуется в элементы DOM (возможно, с помощьюcreateElementметод).InnerHTML быстрее во всех браузерах в соответствии с quirksmode benchmark предоставлено @Pointy.
как читабельности и простота использования, вы найдете меня выбор
innerHTMLovercreateElementв любой день недели в большинстве проектов. Но, как вы можете видеть, есть много точек, говорящих заcreateElement.
вы должны использовать createElement, если вы хотите сохранить ссылки в коде. InnerHTML иногда может создать ошибку, которую трудно обнаружить.
HTML-код:
<p id="parent">sample <span id='test'>text</span> about anything</p>JS код:
var test = document.getElementById("test"); test.style.color = "red"; //1 - it works document.getElementById("parent").innerHTML += "whatever"; test.style.color = "green"; //2 - oooops1) Вы можете изменить цвет
2) вы не можете изменить цвет или что-то еще больше, потому что в строке выше вы добавили что-то в innerHTML и все воссоздано, и у вас есть доступ к чему-то, что больше не существует. Для того, чтобы изменить это вы должны снова getElementById.
вы должны помнить, что это также влияет на любые события. Вам нужно повторно применить события.
InnerHTML отлично, потому что это быстрее и в большинстве случаев легче читать, но вы должны быть осторожны и использовать его с осторожностью. Если вы знаете, что вы делаете, вы будете в порядке.
Comments