Частые ошибки новичков при работе с jQuery

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

Консоль должна быть открыта. Закрытая консоль, конечно же, не ошибка в коде, однако, ошибочный подход во время отладки сценария. Именно консоль поможет быстро сориентироваться в том, где и какая допущена ошибка, а также следить за ходом выполнения сценария. Во всех современных браузерах - этот инструмент присутствует по умолчанию. Например, в FireFox консоль можно вызвать с помощью сочетания клавиш Ctrl + Shift + K или "Меню" > "Разработка" > "Веб-консоль". В Chrome вызывается сочетанием клавиш Ctrl + Shift + J или "Меню" > "Дополнительные инструменты" > "Консоль JavaScript". В Opera - сочетание клавиш аналогичны Chrome, вызов из меню - "Инструменты разработчика" > "Веб-инспектор" ("Инструменты разработчика" предварительно включить в пункте "Другие инструменты"). Кроме того, существуют инструменты/аддоны, как, например, замечательный FireBug под FireFox или Web Developer для Chrome и этот же инструмент для FireFox

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

  1. Оставляем одну новую библиотеку и сразу после неё подключаем плагин jQuery Migrate, который, в большинстве случаев, помогает решить вопрос совместимости.
  2. Без каких-либо дополнений, сами заменяем в плагине удаленные методы на их современные аналоги. Обычно, это такие устаревшие или удаленные методы, как live(), $.browser и т.д.
  3. И конечно же, можно найти современный аналог плагина, который вам понравился. Не зацикливайтесь на одном.

Ну, и примерный порядок подключения:

<script src="/js/jquery-1.11.1.min.js"></script><!-- библиотека jQuery -->
<script src="/js/jquery-migrate-1.2.1.min.js"></script><!-- если требуется -->
<script src="/js/jquery-ui.min.js"></script><!-- если используете jQuery UI -->
<script src="/js/my_scripts.js"></script><!-- ваши коды -->

Код не обернут в конструкцию DOM-Ready. Одна из наиболее популярных ошибок. Если ваш скрипт расположен/подключен в теге <head>, то его нужно обязательно заключить в такой код:

$(document).ready(function(){
    // тут весь ваш код
});
// или сокращенная запись
$(function(){
    // тут весь ваш код
});

Это так называемый "обработчик готовности дерева DOM". Попробую "на пальца" и простым языком объяснить, что это и зачем нужно. Браузер загружает страницу, начиная с первого на ней элемента и движется вниз. Всё, что подключено в теге <head>: CSS, JS и т.д., загрузится и начнёт выполняться раньше, чем дело дойдёт до элементов, которые находятся в <body>. Поэтому, при обращении к элементу из JS-кода, его еще попросту нет на странице. А обёртка, которую я показал выше, откладывает выполнение сценария до тех пор, пока вся структура страницы не будет загружена браузером полностью. Как вариант, который совсем не лишён логики и даже рекомендуется тем же Google, весь свой код можно расположить в конце страницы, перед закрывающим тегом </body>. Так же, хоть и не совсем по теме этого пункта, рекомендуется в некоторых случаях использовать атрибут async для тега <script>.

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

$('static_parent').on('event', 'dinamic_child', handler);
  • static_parent - статичный родительский элемент
  • event - событие
  • dinamic_child - динамический дочерний элемент
  • handler - функция-обработчик

К примеру, в каком-то блоке с классом "my_block", есть несколько ссылок с классом "my_link", при клике на которые, выполнялось какое-то действие. Все они изначально присутствовали при загрузке страницы. Теперь мы добавили еще несколько ссылок с таким же классом, но без делегированной обработки, они будут просто проигнорированы и нужное действие уже не выполнится. Для того, чтоб событие обрабатывалось и на старых, и на новых ссылках, нам нужно записать так:

$('.my_block').on('click', '.my_link', function(){
    // действия при клике
});

! При чём, объект $(this) внутри обработчика - это именно ссылка ".my_link", на которой событие было вызвано, а не родительский элемент ".my_block", как это бы было при обычной записи, а не делегированной. Старайтесь находить ближайший родительский статичный элемент, что ускорит работу кода. Хотя, в качестве такого, можно выбрать и body, и даже document.

Неправильно подобранный селектор. Вообще, эта тема гораздо обширнее, чем звучит, но тут разберём самые основные промахи, которые допускают новички. Селектор, говоря образно, это признак элемента, по которому мы к этому элементу обращаемся или применяем какой-либо из методов. Селекторами в jQuery (и не только), может быть как имя тега, класс элемента (атрибут "class"), его идентификатор (атрибут "id"), так и любые другие атрибуты или же их комбинации. Тем, кто знаком с CSS, можно расслабится, т.к. селекторы jQuery строятся по такому же принципу, как и в CSS, а вот остальным придётся познакомиться с CSS поближе. Парочка примеров:

$('div'); // выберет все элементы "div"
$('#my_element'); // выберет единственный (*см. ниже) элемент с атрибутом id равным "my_element"
$('.my_element'); // выберет все элементы на странице с классом "my_element"
$('.my_element.other_class'); // выберет элементы на странице с классом "my_element", у которых так же есть класс "other_class"
$('#my_element .my_element'); // выберет все дочерние элементы с классом "my_element" у родительского с id = "my_element"
$('[name=my_name]'); // выберет элементы, у которых атрибут name равен my_name
$('[name=^my_name]'); // выберет элементы, у которых значение атрибута name начинается на "my_name"
$(':checkbox'); // выберет все элементы input с типом "checkbox"
// и так далее ...

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


В этой статье точку не поставишь, поэтому следите за её обновлениями и не делайте ошибок или учитесь их исправлять ;)

Incode Pro logo

16 комментариев

Сандрован 28.12.2016 23:17
Статья не ответила на мою проблему, но кое что благодаря ей дало мне подозрения на причины не работающей формы связи в модальном - окне. Подскажите, у меня аж три библиотеки подключены на сайте (www.uvasnachas.ru)не могли бы Вы дать мне пояснения можно ли их сократить хотя бы до двух. Сам я не силён в этом, да что там не силён, я реально слаб! в js и всё что выше html.
Incode 29.12.2016 00:52
@Сандрован, у меня встречный вопрос. А зачем вы подключали несколько библиотек? Причины, по которым так некоторые поступают, это очень старые плагины, которые используют методы, удаленные в новых версиях. Если это ваш случай, то достаточно заменить в плагинах старые методы на их аналоги в более свежих версиях. Это то, что касается версии библиотеки 1.8.3. А относительно версий 1.12.4 и 1.11.2, то тут нет каких-либо причин держать их обе. Оставляете одну наиболее свежую, т.е. 1.12.4.
И еще, возвращаясь к версии 1.8.3, вы можете подключить официальный плагин jQuery Migrate, например, версии 1.4.1 (подключать нужно сразу после подключения jQuery). В этом случае, оставив всего одну библиотеку 1.12.4, вы получите работающие с ней старые плагины. Но этот подход можно с уверенностью назвать "костылём".
Сандрован 30.12.2016 03:14
Версия библиотеки 1.8.3 нужна для работы Анимации на главной страницы, 1.11.2 я удалил по вашему совету(я её оставил для работы меню, которое я временно удалил с сайта оставив подключенной библиотеку и настройки css, на случай если решу вернуть меню) как и следовало ожидать ни чего не случилось, ни в плохую, ни к сожалению в хорошую сторону. А анимация увы не хочет работать на новых библиотеках. Сайт то в принципе простой, html да css, создавая его я руководствовался тем, что Яндекс высоко ранжирует сайты на чистом html без всяких конструкторов типа вордпресс или джумлы. Но естественно хочется чтоб технически сайт не отставал по удобству для пользователей, да и без почтовой формы сайт теряет дополнительные возможности коммерции. Спасибо за ответ. Мне даже половины вашего ответа не смогли выдать на форуме (cyberforum), страшные делопуты там обитают ))
Incode 30.12.2016 09:16
1.8.3 нужна для работы Анимации на главной страницы

@Сандрован, если речь идёт о слайдере, то его последняя версия работает не то что с версиями первой серии, но и со второй и даже с версиями 3.x. Другой анимации, связанной с JS, я не заметил. Поэтому, смело подключаем свежий плагин ResponsiveSlides и забываем про версию jQuery 1.8.3, как страшный сон ;)
страшные делопуты там обитают
Я на cyberforum-е так же изредка консультирую, поэтому тоже попадаю под это определение :)
Сандрован 31.12.2016 06:34
У меня просто нет слов, действительно работает!Всего то заменил два файла JS, удалил подключенную 183 JQ-библиотеку и о чудо слайдер работает )) СПАСИБО, Вы в двух своих ответах смогли помочь мне больше чем вместе взятые ответы на всех сайтах куда я писал. Теперь осталось решить проблему с отправкой писем из модального окна и я счастлив на все 100% )) Ещё раз большое человеческое спасибо!!!
Сандрован 31.12.2016 06:41
По чаще бывайте на cyberforum-е, Вас там явно не хватает. Вы исключение из правил и определений. ))
Сандрован 31.12.2016 06:56
А относительно версий 1.12.4 и 1.11.2, то тут нет каких-либо причин держать их обе. Оставляете одну наиболее свежую, т.е. 1.12.4.

Блииин, вот тут теперь у меня беда, перестали открываться модальные окна после удаления всех библиотек кроме 1.12.4, может лучше оставить 1.11.2 версию? Окна были подключены на ней. ((
Incode 31.12.2016 10:20
может лучше оставить 1.11.2 версию?
Если не хотите разбираться в причинах, то оставляйте. По крайней мере, эта версия ощутимо лучше, чем любые другие, вышедшие до 1.9.
Кстати, если вам не нужна поддержка старых ослов, то попробуйте подключить самую свежую версию 3.1.1
Сандрован 31.12.2016 16:57
Ох, конечно же я бы хотел разобраться, но увы мозгов недостаточно. В последствии оказалась такая штука, что в зависимости от того, в каком месте я подключаю библиотеку (head или body), работают либо окна, либо слайдшоу. Понимаю что что-то не так делаю, но не понимаю что именно ((
С Новым годом Вас, удачи, здоровья и развития.
Incode 31.12.2016 17:37
но не понимаю что именно
@Сандрован, весь код, должен идти после подключения библиотеки, т.е. сначала подключаем библиотеку, а только потом плагины или свой код. Кроме того, если ваш код или код инициализации плагинов располагать в теге <head>, то его нужно оборачивать в конструкцию DOM-Ready:
$(function(){
    // Весь код jQuery
});
Если же ваш код находится в конце страницы, то эта конструкция не обязательна. Собственно, об этом я писал выше.
P.S. С наступающим вас и всяк сюда зашедших. ;)
Сандрован 01.01.2017 11:39
В том то и кактус, пробовал, не получилось у меня, видно я безнадёжно криворук ((
Сандрован 08.01.2017 09:36
Кажется я нашёл причину, дело в том что мне не понравилось название класса scc для слайдшоу "callbacks" что переводится вроде как обратный звонок, подумав что это нелогично, я сменил его на slidbox, в тот же момент я подключал дополнительное меню на другой версии библиотеки и когда увидел изменившийся вид слайд-шоу, подумал что это конфликт библиотек, порыскав в инете нашёл такой костыль
<script type="text/javascript">
jQuery.noConflict();
</script> Почему то сработало. НО!!! Дело оказалось в том что "callbacks" этот прописан в БИБЛИОТЕКЕ jQuery и я так понимаю это что то вроде тега, и может применяться для разных эффектов и ситуаций. Теперь попробую переписать начисто страницу и заново подключить модальные окна с формой связи.
Сандрован 08.01.2017 09:38
Ах да, С прошедшими праздниками ))
kaktixus 17.11.2017 15:05
@Incode,
Привет ! меня есть несколько вопрос. Но с начало спасибо за статью. Очень полезная. Итак приступим. Скажи чес отличаются версии jquery, где первый префикс 1, 2, 3 ?
Incode 17.11.2017 19:17
@kaktixus, Первая редакция jQuery (версии 1.x) поддерживала IE 6/7/8. На сегодняшний день, эти браузеры, которые древнее дерьма мамонта, уже не актуальны. Поэтому в версиях jQuery 2.x и 3.x - они не учитываются, что позволило уменьшить код и использовать технологии, которые актуальны на сегодняшний день. В версия jQuery 3.x был добавлен новый функционал, удалены древние методы (в 2.x тоже удаляли мусор) и в принципе, библиотека была основательно переработана, с учетом прошлых ошибок.
kaktixus 21.11.2017 17:21
@Incode, Спасибо за информацию. Ты мне очень помог!
Ваш комментарий:
X