Website development
jQuery
Comments 59
+1
Век живи — век учись. Спасибо, не знал такого способа.
+10
Сделайте, пожалуйста, наглядное сравнение производительности пары плохих вариантов из начала статьи и правильного. Очень удобно было бы посмотреть такой тест через сервис jsperf.com
+2
и еще пример построения и вставкой dom цикле и второй вариант — с использованием documentFragment, чтобы на лицо было видно его большое преимущество. Перестроение DOM при изменении геометрических свойств — самая ресурсоемкая операция, поэтому никаких append в цикле.
-6
Будет работать немного медленней, но не ощутимо для пользователя. Хотя опять же таки, смотря сколько у Вас в целом js кода и количество данных.
+4
По поводу ваших созданий таблиц читаем "jQuery изнутри — парсинг html":

Для случая с <td>Привет!</td>, код превратится в <table><tbody><tr><td>Привет!</td></tr></tbory></table>, а указатель на контейнер с нужным нам результатом будет смещен на глубину в 3 тега, то есть в <tr> вместо <div>, который был создан внутри safeFrag в самом начале


Да и вообще лучше почитать всю серию «jQuery изнутри». Там много описано на эту тему и, в основном, более корректно и полно.
+5
Да что ж такое, в третьем посте подряд создают DOM-дерево руками. Неужто времени не жалко?
+8
Строить DOM создавая отдельно каждый элемент — это удар по производительности.
Первый пример из статьи будет работать в 10-100 раз быстрее, особенно в цикле.
Конечно так складывать строчки не очень красиво, зато работает быстро.

Ну и конечно никто не запрещает использовать шаблоны для построения DOM, хотя бы тем же jQuery.tmpl
+2
А по моему все эти мудреные цепочки и вложенные методы jquery читаются хуже, чем старое доброе сложение строчек в цикле. +)
-1
Быстрее будет не складывать строчки, а складывать их в массив и потом join-ить:
var html = [];
for (var i=0; i<100; i++) {
  html.push('<div>');
  html.push(i);
  html.push('</div>');
}
$('#div').append(html.join(''));

Операция join быстрее срабатывает, чем множество +
0
Только если говорить об IE. Разница между склеиванием массива и конкатенацией во всех более мение новых браузерах не настолько велика. Хотя да, отрабатывать будет чуть быстрее. Жаль что в javascript нет своего string builder-а
0
jsperf.com/concat-vs-join444 — только если так. Вот только добавление элемента в массив операция даже более ресурсоемкая нежели конкатенация строк. Так что если делать все так как рекомендует lexxpavlov, то производительность в современных браузерах (в случае сборки шаблона) упадет в разы.
+1
Давайте глянем полный пример:
jsperf.com/concat-vs-join444/2

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

В остальных браузерах однозначно имеет смысл конкатенировать, а не джоинить.
0
И правда, потестил сейчас оба варианта. Конкат быстрее оказывается.
Странно, потому что читал о таком способе и там убеждали в быстроте join, и тесты приводили. Я тогда не проверил сам, но запомнил. Извиняюсь, что привёл непроверенную информацию…
Кстати, интересно, что по тестам jsperf.com/concat-vs-join444/2 в некоторых браузерах join всё-таки быстрее. Но в остальных браузерах настолько медленнее, что небольшое превосходство в некоторых браузерах не окупится.

Вот мой тест: jsperf.com/concat-vs-join445
Интересно то, что при повышении объема данных join становится хуже и хуже…
+13
Вам следует указать в статье, что такой способ создания элементов черезвычайно ресурсоемкий, и подходит только для создания небольшого количества элементов, и уж точно его нельзя использовать в цикле, раз уж ваша статья предназначена для новичков.
+8
Простите
Сложно сказать хороший это код или нет, но он явно недружелюбный.

Это на правах шутки?
+4
Простите, а зачем, если есть вполне отличные шаблонизаторы? Тот же mustache, dust.js и иные.
В куче такого кода через два месяца не разберешься.
+7
1) Да, jQuery позволяет так делать, но как минимум этого не стоит делать.
2) используйте хотя бы createDocumentFragment для сборки всего этого добра. как показывают бенчмарки — все это добро ускорится в разы.
3) Метод с конкатенацией строк отрабатывает в десятки раз быстрее.

Статья имеет смыл только в качестве пособия о возможностях jQuery, Использовать ЭТО в реальных проекта крайне не рекомендуется. Лучше уж использовать какие-нибудь шаблоны.
+1
Еще стоит отметить, что использовать each для обхода массива (в примере с таблицей и списками) более ресурсоемкая операция чем:

for (var i = 0, l = arr.length(); i < l; i++) {
    ...
}


При этом кода не становится больше, а воспринимается он гораздо легче.
ИМХО пример с таблицей вообще ужасен.
-4
Ну статья о jQuery. Если писать все на чистом js все будет быстрее и это очевидно. Если Вам не нравится, не пользуйтесь.
+1
Да дело не в тормознутости jQuery, дело в неверном подходе.

На чистом js это будет что-то вроде:
var table = document.createElement('table')
var thead = document.createElement('thead')
var tr = document.createElement('tr')
var td = document.createElement('td')
var text = document.createTextNode('текст')
td.appendChild(text)
tr.appendChild(td)
thead.appendChild(tr)
table.appendChild(thead)

за корректность не ручаюсь, но в таком духе. Прямо как в известном диалоге: открыла чемодан, достала сумочку, закрыла чемодан, открыла сумочку, достала кошелёк, закрыла сумочку, открыла чемодан, положиле сумочку, закрыла чемодан, открыла кошелёк…

Как вам тут уже правильно заметили, написать
<table><thead><tr><td>текст</td></tr></thead></table>
и позволить браузеру распарсить это и построить дерево самому — значительно проще и понятнее, работает в десятки раз быстрее, чем если это делать на js, особенно для большого числа элементов.
+1
Суть в том что кто-нибудь напишет «а вот как можно делать» а потом впечатлительные люди и вправду станут так делать. А потом сиди и рефактори за них.
-3
Вы правы, я даже с Вами согласен, но я не думаю что оно работает настолько медленно что бы так критиковать. Если брать даже очень большие проекты на чистом js — они все равно будут немного тормозить, так как в этом весь javascript, небольшие задачи он решает очень неплохо, даже вот такими методами.
+1
Оно работает именно «настолько медленно». В сложном интерфейсе, когда динамически подгружается десяток блоков со сложной версткой вы сразу почувствуете лаги, если не использовать шаблоны, data-binding, и прочие прелести современных фреймворков (knockout, backbone, angular).
Посмотрите как устроен любой сложный клиентский интерфейс, VK, Twitter и т.д

Все сообщество веб-разработчиков бьется за каждую миллисекунду и мгновенную отзывчивость интерфейса, а вы предлагаете самый худший вариант создания dom-дерева, отсюда и критика.
+1
jsperf.com/dom-gen — как-то так… Код не оптимален, буду рад если кто-то скажет как написать последние 2 теста правильно. Я увы давно на старом добром JS Этого не делал.
0
С увеличением объема (скажем не простенький списочек а здоровый кусок шаблона) разница будет только увеличиваться.
0
То есть вы считаете что фанаты jQuery даже массив обходят при помощи each? Даже если объем кода увеличивается?
+1
а еще быстрее будет
for (var i = arr.length(); i--; )

это конечно для перебора, если нам не важен порядок.
0
Это уже экономия на спичках. Тогда уже можно было бы использовать Array.map
0
Ексть еще интересный способ динамического создания элементов, основным преимуществом которого является удобная поддержка с точки зрения взаимодействия с верстальщиком.

Идея: скрытый элемент в HTML-коде, затем через clone() получается его копия и уже в нее через селекторы вставляются нужные значения. Эдакий «шаблонизатор для бедных», когда по каким-то причинам настоящий шаблонизатор не используется.

<div class="myclass tpl hidden">
      <h1></h1>
</div>
...
<div id="parent"></div>


var tpl = $('.tpl').clone();
tpl.removeClass('hidden tpl');
tpl.find('h1').text('Hello!');
tpl.appendTo('#parent');


Есть и минусы, конечно. Например, наличие в коде лишнего элемента может дать погрешность, если в примере выше потребуется посчитать все элементы с классом myclass — нужно быть внимательным. Плюс — никаких тэгов в джавасрипте.
0
В общем-то clone даже не особо нужен, что мешает сразу нужную разметку вставить и скрыть ее до тех пор, пока она не понадобится?
0
В этом частном случае — да, но, как правило, подобным способом динамически создаются повторяющиеся элменты списка, строки таблицы либо целые однотипные блоки. Т.е. шаблон не должен исчезать.
0
Попробуйте запустить свой «Вот еще интересный вариант:», осознайте, что он на самом деле вставит в DOM.
+1
Тогда к чему слова «Сложно сказать хороший это код или нет»? Этот код явно делает не то, что думал человек, написавший его.
«Статья рассчитана на начинающих», а вы оставляете такое без явного комментария о том, что такой код писать не надо.
-7
Для меня самым не очевидным в jQuery оказался тот факт, что обработчики событий «наслаиваются» друг на друга. То есть на элемент #id событие $('#id).click() может повесится несколько раз, и автоматически не перезаписываются.
Конечно, unbind меня спас. Но сам факт хранения где-то в памяти богом забытого обработчика для элемента — смущает
+3
Возможно я открою для вас секрет, но обработчики событий в jQuery навешиваются через стандартный eventListener браузера. И фишка событий в Dom в этом и состоит, что события наслаиваются и всплывают. Без этого нельзя было бы реализовать делегацию событий, без этого много чего пришлось бы реализовывать с костылями. Да и во всех других системах с Ui ивентов можно навесить столько, сколько угодно.
0
К слову, раз уж возникают вопросы…

jsfiddle.net/a6rsx/ — полное управление ивентами. Тобиш возможность контролировать порядок исполнения, временно отключать лишние ивенты и т.д.
+2
OMG, вы сейчас серьезно?
Я так понял что вы изучали только jQuery а не JavaScript… Прочтите пару книг не о jQuery.
0
Что же столько негатива то, это был одним из моих первых опытов работы с DOM-моделью как таковой. Слышал о ней, читал, пробовал понемногу обращаться к элементам — но как оказалось раньше всё было довольно поверхностным. Я не говорю что наслаивание обработчиков это плохо, это всего лишь было для меня не очевидно, в отличии от перестроения модели при добавлении нового элемента, например.
0
По поводу наслаивания (я так понимаю вы о всплытии событий?) — есть дерево элементов. Как только произошел клик по одному из них, событие передается дальше, вниз по дереву, к основанию. так как (если не вдаваться в оформление) это логично — кликнул на блок, а он внутри другого блока, по нему выходит тоже кликнули, ну и т.д. до document.

То что можно навешивать много обработчиков одного события на один элемент — это уже мелочи.
0
Не совсем, я добавлял элемент из одной таблицы в другую с помощью .clone().after() и вешал на класс, который был у новой строки строки, событие $('.classname).onclick().
Проблема была в том, что для первого добавленного элемента, событие срабатывало 1 раз.
Для второго — два раза. Ну и так далее.

Поскольку при каждом новом добавлении элемента я вешал НОВЫЙ .onclick(), в добавок к старому.

Вы говорите немного о другом, вложенность по дереву меня не удивляет)
+1
1) у метода clone есть параметр, который отвечает за сохранение навешанных событий у элемента.
2) логичнее в этом случае использовать делегирование событий.
0
Спасибо, буду знать. Но в моём случае объект, от которого наследовалась строка, обладал другим функционалом, и на наследуемый элемент в любом случае вешался новый обработчик.

Видимо, по-умолчанию наследование обработчиков выключено (не замечал лишних срабатываний).

А, ну да: withDataAndEvents (default: false)
0
Не совсем, я добавлял элемент из одной таблицы в другую с помощью .clone().after() и вешал на класс, который был у новой строки строки, событие $('.classname).onclick().

А зачем? Раз уж добавляли методом .clone().after(), то надо было сразу вешать .click()
0
Вот об этом не подумал. Действительно, так было бы гораздо лучше.
+1
При работе с DOM ещё полезно знать, что jquery-селекторы, это, по сути, массивы — таким образом можно быстро достучаться до чистой дом-ноды и применить к ней нативные(и быстрые) методы:
$('#element')[0] == document.getElementById('element')
+1
Хорошо описаны возможности JQuery, но я бы делал это на чистом JS, по нескольким причинам:
1) Это быстрее
2) Я знаю как это делается на JavaScript
3) Я не смогу запомнить как это делает JQuery =)
0
1) очевидно но плохо поддерживается. Идеальный компромис — конкатенация строк или шаблонизаторы.
3) ну это вы преувеличиваете.
Only those users with full accounts are able to leave comments., please.