Советы по jQuery

Programming
Предыдущий Следующий

  Здесь приведен ряд очень простых правил, следуя которым, ваше сотрудничество с jQuery не будет омрачено скрежетом напрягшегося браузера. Конечно, не так часто случается, что скорость работы javascript’а оказывается критичной, однако такое все же может произойти, и произойти в самый неподходящий момент. Поэтому, лучше держать эти правила в голове и не пренебрегать ими.

1. Эффективный поиск элементов

Быстрее всего происходит поиск элементов по идентификатору: $('#someId'), вторым по быстродействию, является поиск по имени тега: $('tagName'). Высокая скорость их выполнения связана с тем, что для их реализации используются внутренние функции javascript: getElementById() и getElementsByTagName(). В связи с этим, появляются несколько правил.

(Для большей наглядности, укажу текст страницы, к которому будут применен JS-код из примеров)
 

<divid="content">
  <formmethod="post"action="/">
    <h2>Выбери цвет</h2>
    <ulid="color_light">
      <li><inputtype="radio"class="on"name="light"value="red"/>Красный</li>
      <li><inputtype="radio"class="off"name="light"value="yellow"/>Желтый</li>
      <li><inputtype="radio"class="off"name="light"value="green"/>Зеленый</li>
    </ul>
    <inputclass="button"id="color_button"type="submit"value="Go"/>
  </form>
</div>

 

1. Если вы ищете один элемент, используйте поиск по идентификатору:
$('#color_button') – будет выполнен максимально быстро
$('#content .button') – будет медленнее
$('.button:first') – еще медленнее

2. Если вы ищете группу элементов, указывайте ближайшего общего родственника, обладающего идентификатором:
$('#content input') будет эффективнее, чем просто $('input').

3. Если вы ищете элементы по классу, указывайте имя тега:
$('input.button') выполнит поиск быстрее, чем $('.button'). В первом случае, jQuery вначале найдет все элементы input, и уже среди них будет искать элементы с классом button. А во втором случае, для этого будет произведен перебор всех элементов страницы.

Из всего сказанного, можно вывести два основных правила:
1) Для поиска одного элемента, используйте поиск по id: $('#someId')
2) При поиске группы элементов, старайтесь придерживаться следующей формулы: $('#someId tagName.someClass')

И еще, не пытайтесь улучшить поиск по id с помощью следующих комбинаций:
$('tagName#someId')
$('#wrapId #someId')
Это только замедлит выполнение поиска.
 

2. Используйте результат поиска элементов повторно

 Не следует производить поиск одних и тех же элементов снова и снова, это достаточно дорогостоящая процедура, даже если вы используете самый быстрый селектор:

$('#myElement').bind('click', function(){...});
. . .
$('#myElement').css('border', '3px dashed yellow');
. . .
$('#myElement').fadeIn('slow');


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

var myElement = $('#myElement');
. . .
myElement.bind('click', function(){...});
. . .
myElement.css('border', '3px dashed yellow');
. . .
myElement.fadeIn('slow');

 

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

window.elements;
function init()
{
  elements = $('#someId tagName.someClass');
}


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

$('#myForm input:checkbox') // все флажки
$('#myForm input:text') // все текстовые поля
$('#myForm input:text[value != ""]') // все непустые текстовые поля
. . .


Вместо этого, можно найти все элементы формы один раз, и при необходимости доставать оттуда необходимые:

var inputs = $('#myForm input');
inputs.filter(':checkbox') // найдем все флажки
inputs.filter(':text') //найдем все текстовые поля
inputs.filter(':text[value != ""]') // найдем все непустые текстовые поля
. . .


Или, вам может потребоваться совершать много манипуляций с элементами списка, в том числе удалять и добавлять их. В таком случае, «кэшировать» элементы списка не будет хорошей идеей, поскольку их состав будет постоянно меняться, а «кэш» оказываться неактуальным. Однако, можно сохранить объект самого списка в глобальной переменной, что тоже значительно сократит вычислительные затраты:

myList = $('#myList');
. . .
myList.find('li:first').remove(); // найдем и удалим первый элемент списка
myList.find('li.showed').hide(); // скроем все элементы списка с классом showed
 

3. Избегайте лишних манипуляций c DOM

Основной идеей здесь является то, что если вы хотите внести ряд изменений на странице (добавить/изменить элемены), проделывайте эти манипуляции локально и только после этого вносите изменения в DOM. Например, если вы хотите добавить в список сто новых элементов, то ошибочным будет делать это поэлементно:

var top_100_list = [...]; // содержимое новых элементов
$mylist = $('#mylist'); // необходимый список

for (var i=0; i< top_100_list.length; i++)
  $mylist.append('<li>' + top_100_list[i] + '</li>');


гораздо эффективнее будет вставить сразу все элементы:

var top_100_list = [...]; // содержимое новых элементов
var li_items = ""; // вставляемый html-текст
$mylist = $('#mylist'); // необходимый список

for (var i=0; i< top_100_list.length; i++)
  li_items += '<li>' + top_100_list[i] + '</li>';
$mylist.append(li_items);


Еще больший выигрыш можно получить, если группа вставляемых элементов окажется «обернутой» одним элементом. Поэтому, если бы у нас была задача заменить содержимое списка сотней новых элементов, то самым оптимальным, был бы такой вариант:

var top_100_list = [...]; // содержимое новых элементов
var new_ul = "<ul id='mylist'>"; // вставляемый html-текст
$mylist = $('#mylist'); // необходимый список

for (var i=0; i< top_100_list.length; i++)
  new_ul += '<li>' + top_100_list[i] + '</li>';
new_ul += "</ul>";
$mylist.replaceWith(new_ul);


Изменять элементы локально, поможет метод clone(), который создает копии элементов, вместе со всем их содержимым. Произведя все необходимые изменения с копиями, можно вставить их обратно в DOM, вместо старых версий (это можно сделать с помощью метода replaceWith()).
 

4. Используйте делегирование событий

Иногда, приходится устанавливать одинаковые обработчики событий на большую группу элементов. Например, может потребоваться установить обработчики нажатия мышью, элементам списка. В таких случаях, вместо того, чтобы устанавливать обработчики на каждый элемент списка, можно установить один обработчик на сам список. Как известно, стандартные события javascript, вызванные на каком-либо элементе, затем вызываются на всех его предках (родительском элементе, затем прародительском и.т.д). Поэтому, после того, как событие произойдет на конкретном элементе списка, оно будет вызвано на объекте самого списка. Понять, у кого именно произошло событие, поможет передаваемый в обработчик объект event, а точнее, его свойство event.target. Оно всегда содержит DOM-объект первоначального источника события:
 

$('#myList').click(function(event){
  $(event.target).addClass('clicked'); // добавим нажатому элементу класс clicked
});
5. Используйте ООП

 Одна из проблем разработки на джава скрипте, это то что все как правило пишут в отдельном набор каких нибудь функций в глобальном контексте и когда файлов таких стает несколько то функции могут переопределять друг друга по случайности. Выход с данной ситуации это создавать объект по имени файла или же другим понятным именем. Те файлы (объекты) что много раз переиспользуются лучше назвать какими то более абстрактными вещами (например ARRAY_UTILS.js), файлы в которых есть индивидуальный для страницы функционал лучше назвать по названию самой страницы, то есть если у нас страницы называется Report.aspx то логично к ней создать js файл с объектом

var REPORT_PAGE_CLASS = function() {
     var scope = this;
     …
          this.someFunction = function() {
                  …
               …
}

       $(function() {
                  …
               scope.someFunction();
               …    
});
};

var REPORT_PAGE = new REPORT_PAGE_CLASS();
    
Все что внутрик обьявляется как через var недоступно из вне, а все что через this.fg доступно как свойства или функции

И дальше если мы используем в HTML разметке вставки с кода, то будем обращаться к объекту REPORT_PAGE.
 

Самостоятельный отпуск Опыт заказа вывоза мусора в Киеве Магія зміни: Від ночі до дня
Магія Вечірнього Неба: Відлякуйте втомленість дня і зануртеся у світ загадок і краси