maxidebox@list.ru | +7 (929) 701 21 71
Велосипеды на Javascript и jQuery

Велосипеды на Javascript и jQuery

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

Константы в коде

Эта проблема касается не только javascript, а программирования в целом. Рассмотрим пример:

  
$elem.on('keydown', function(e) {
    if (e.keyCode == 27) {
        //...
    }
});   
  

Что за магическое число 27? Люди, которые часто сталкиваются с кодами сразу скажут — это же клавиша ESC. Но большинство разработчиков, особенно начинающих, либо не помнят эти коды, либо не знают вообще, и сталкиваясь с кодами, вынуждены в очередной раз лезть в поисковую систему и тратить время.

Можно конечно добавить комментарий в коде, что это обработка нажатия клавиши ESC, но гораздо эффективнее было бы ввести константу, например, KEY_ESC = 27

Получение идентификаторов

Часто возникает необходимость получить идентификатор элемента (комментария, поста, пользователя и т.п.), чтобы выполнить какие-нибудь действия. (например, оценить комментарий при помощи ajax). И часто можно встретить подобный подход:

  
var id = $(this).attr('id').substring(8);   
  

Как и в предыдущем примере разработчику приходится гадать — что же это за число 8. Лезть в html код и т.п.

Бывают примеры и хуже (строчка скопирована с реального проекта):

  
var last_id = $('#answer_pid' + id + ' li:first div').attr('id').substr(7);   
  

Малейшее изменение верстки приведет к тому, что js код придется править.

Иногда бывает такое:

  
<div class="comment" id="comment_123"></div>

var id = $(this).attr('id').substring("comment_".length);   
  

Уже лучше (по крайней мере нет вшитых чисел), но все равно данный подход слишком сильно привязывает js код к html.

На мой взгляд гораздо лучше использовать data-* параметры, например

  
<div class="comment" data-id="123"></div>   
  

тогда получить идентификатор будет очень просто:

  
var id = $(this).attr('data-id');   
  

или

  
var id = $(this).data('id');    
  

(Про отличия в работе attr и data есть множество статей)

$.post

Как известно — в jquery есть метод для работы с ajax — $.ajax. К нему есть несколько shorthand функций, таких как $.get, $.load, $.post и т.п. Данные функции были добавлены специально, чтобы облегчить часто выполняемые действия (подгрузить скрипт, json, выполнить post запрос), но в реализации все эти методы ссылаются на $.ajax.

Лично я никогда не использую shorthand функции, и вот почему:

В коде начинающих или малоопытных разработчиков можно встретить несколько разных стадий:

Начальный

  
$.post(url, data, function(data) {
            data = $.parseJSON(data);
            //...
});   
  

Добавляется try catch блок

  
$.post(url, data, function(data) {
      try {
                data = $.parseJSON(data);
            } catch (e) {
                return;
            }
            //...
});   
  

Узнаем из документации, что в $.post последним параметром можно передать dataType (который пропадает в бездне кода, если success функция не влезает в экран).

  
$.post(url, data, function(data) {
    //...
}, 'json');   
  

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

Если же разработчик решил к $.post добавить обработчик ошибок, то получается нечто вроде:

  
$.post(url, data, function(data) {
    //...
}, 'json').error(function() {
   ///
});
  

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

  
$.ajaxSetup({
    error: function() {
        //Показать окошко о том, что произошла ошибка
    }
});   
  

Вернемся к $.post. Как показано выше — использование $.post делает код ужасным (особенно с dataType в непонятном месте). Перепишем последний пример на $.ajax. На мой взгляд данный подход читабельнее и проще в поддержке.

  
$.ajax({
    type: "POST"
    url: url,
    data: data,
    dataType: "json",
    success: function(data) {
        //
    },
    error: function() {
        //
    }
});   
  

Обработчики событий к нескольким элементам

Часто бывает необходимость добавить обработчики событий к элементам страницы (например, кнопка «удалить сообщение»). И зачастую можно встретить подобный подход:

  
$('.comment a.delete').click(function(){
    //
});   
  

Возникает проблема — добавить этот же обработчик к новому элементу (например к динамески подгруженному комментарию). И тут я видел множество решений, включая переопределение всех обработчиков заново (нередко копипастом содержимого обработчиков):

  
$('.comment a.delete').unbind('click').click(function() {
    //
});   
  

Решение: в jQuery 1.7 есть метод on, который привязывает обработчики события, фильтруя элементы по селектору. пример:

  
$('body').on('click', 'a.external', function(e) {
  //функция будет вызвана при клике на любую ссылку с классом external
});   
  

При этом важно, что данный обработчик работает и для динамически создаваемых объектов.

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

  
$('body').on('mousemove', selector, function() {
  //
});   
  

Namespaced events

Несмотря на то, что namespaced events были добавлены в jQuery 1.2 — ими мало кто пользуется (Мне кажется большинство людей просто не знают о них).

Рассмотрим пример:

  
$('a').on('click', function() {
  //обработчик 1
});
$('a').on('click', function() {
  //обработчик 2
}); 
  

Теперь предположим, что нам нужно удалить второй обработчик от ссылок. Но вот ведь незадача — $('a').off('click') удалит оба обработчика. На помощь приходит namespaced events.

Перепишем код выше:

  
$('a').on('click.namespace1', function() {
  //обработчик 1
});
$('a').on('click.namespace2', function() {
  //обработчик 2
});   
  

Теперь становится возможным удалить второй обработчик при помощи вызова $('a').off('click.namespace2');

Подробнее о namespaced events можно прочитать здесь: docs.jquery.com/Namespaced_Events

Голосов: 215 | Просмотров: 482