Высокопроизводительный динамический HTML
Изменение дерева документа при помощи innerHTML
var i, j, el, table, tbody, row, cell; el = document.createElement("div"); document.body.appendChild(el); table = document.createElement("table"); el.appendChild(table); tbody = document.createElement("tbody"); table.appendChild(tbody); for (i = 0; i < 1000; i++) { row = document.createElement("tr"); for (j = 0; j < 5; j++) { cell = document.createElement("td"); row.appendChild(cell); } tbody.appendChild(row); }
(сильно быстрее во всех браузерах класса А)
var i, j, el, idx, html; idx = 0; html = []; html[idx++] = "<table>"; for (i = 0; i < 1000; i++) { html[idx++] = "<tr>"; for (j = 0; j < 5; j++) { html[idx++] = "<td></td>"; } html[idx++] = "</tr>"; } html[idx++] = "</table>"; el = document.createElement("div"); document.body.appendChild(el); el.innerHTML = html.join("");
Замечание: прочитайте http://www.julienlecomte.net/blog/2007/12/38/
Изменение дерева документа при помощи cloneNode
var i, j, el, table, tbody, row, cell; el = document.createElement("div"); document.body.appendChild(el); table = document.createElement("table"); el.appendChild(table); tbody = document.createElement("tbody"); table.appendChild(tbody); for (i = 0; i < 1000; i++) { row = document.createElement("tr"); for (j = 0; j < 5; j++) { cell = document.createElement("td"); row.appendChild(cell); } tbody.appendChild(row); }
(быстрее по всех браузерах класса А, иногда значительно быстрее)
var i, el, table, tbody, template, row, cell; el = document.createElement("div"); document.body.appendChild(el); table = document.createElement("table"); el.appendChild(table); tbody = document.createElement("tbody"); table.appendChild(tbody); template = document.createElement("tr"); for (i = 0; i < 5; i++) { cell = document.createElement("td"); template.appendChild(cell); } for (i = 0; i < 1000; i++) { row = template.cloneNode(true); tbody.appendChild(row); }
Замечание: расширенные свойства (expando properties) и прикрепленные обработчики событий будут утеряны!
Изменение дерева документа при помощи DocumentFragment
DocumentFragment
(DOM Level 1 Core) является облегченным вариантомDocument
.- Он поддерживает только ограниченное число обычных DOM-методов и свойств.
- Реализация в IE интерфейса для
DocumentFragment
не соответствует спецификации W3C и возвращает обычный объектDocument
.
var i, j, el, table, tbody, row, cell, docFragment; docFragment = document.createDocumentFragment(); el = document.createElement("div"); docFragment.appendChild(el); table = document.createElement("table"); el.appendChild(table); tbody = document.createElement("tbody"); table.appendChild(tbody); for (i = 0; i < 1000; i++) { ... } document.body.appendChild(docFragment);
Уменьшайте число обработчиков событий (1/2)
- Прикрепление обработчика событий к сотням элементов весь ресурсоемко
- Наращивание количества обработчиков событий чревато потенциальными утечками памяти
- Решение: использовать
event delegation
, технику, базирующуюся наevent bubbling
<div id="container"> <ul> <li id="li-1">List Item 1</li> <li id="li-2">List Item 2</li> <li id="li-3">List Item 3</li> <li id="li-4">List Item 4</li> <li id="li-5">List Item 5</li> ... </ul> </div>
Уменьшайте число обработчиков событий (2/2)
YAHOO.util.Event.addListener("container", "click", function (e) { var el = YAHOO.util.Event.getTarget(e); while (el.id !== "container") { if (el.nodeName.toUpperCase() === "LI") { // Что-нибудь делаем... break; } else { el = el.parentNode; } } });
Уменьшайте отрисовки (reflows)
- Отрисовка экрана происходит каждый раз при манипуляциях с DOM-деревом.
- У браузеров есть ряд оптимизаций, чтобы уменьшить число отрисовок, в частности:
- Изменение невидимого элемента (
display:none
) не вызывают отрисовку - Изменение элемента, не входящего в DOM («off-DOM») не вызывает отрисовку
- Изменение невидимого элемента (
- Групповое изменение стилей:
- Изменяйте значение атрибута
style
при помощи методаsetAttribute
(не работает в Internet Explorer). Пример:
el.setAttribute("style", "display:block;width:auto;height:100px;...");
- Изменяйте значение свойства
cssText
объектаstyle
. Пример:
el.style.cssText = "display:block;width:auto;height:100px;...";
- Более масштабируемо: изменяйте название CSS класса у элемента. Пример:
YAHOO.util.Dom.replaceClass(el, "foo", "bar");
- Изменяйте значение атрибута
Разные советы…
- Может быть, стоит использовать событие
onmousedown
вместоonclick
- Используйте как преимущество удаление небольшой задержки между нажатием кнопки мыши и ее освобождением пользователем.
- «Переключите ваш код на первую передачу»: устраните частые и ресурсоемкие действия
- Смотрите http://yuiblog.com/blog/2007/07/09/downshift-your-code/