Обработка динамически добавленных в DOM элементов

jQuery работает с элементами, которые были на странице на момент инициализации кода. Если добавляются новые элементы — при помощи ajax’а или функций типа append() — то события не затрагивают их.

Как же работать с новыми созданными элементами DOM?

Оказывается для динамических элементов используется делегированная обработка событий.

Допустим на странице есть список (ul), на элементах которого необходимо обрабатывать событие click. Если после установки соответствующих обработчиков, в список будут добавлены новые элементы, то они уже не будут реагировать на «клики», поскольку непосредственно к новым элементам, обработчики прикреплены не были. Эта особенность может породить много проблем и коварных логических ошибок.

Для таких случаев jQuery имеет возможность организовывать так называемую делегированную обработку событий. В этом случае, jQuery вместо заданного обработчика (в параметре handler) устанавливает собственный специальный обработчик. Причем он не устанавливается непосредственно на элементы, на которых необходимо обрабатывать события (назовем их inner-элементами), а на содержащие их элементы (назовем их outer-элементами. Получается, что inner находятся внутри outer). После того, как событие происходит на одном из элементов inner, оно начинает подниматься вверх по иерархии DOM. В какой то момент оно оказывается на одном из элементов outer, на котором срабатывает специально установленный обработчик, который проверяет, поднялось ли событие от одного из элементов inner. Если это так — запускается обработчик handler.

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

Чтобы организовать делегированную обработку, необходимо во втором параметре метода on задать селектор. В этом случае роль outer-элементов будут играть элементы к которым был применен метод, а роль элементов inner — элементы, находящиеся внутри outer и удовлетворяющие заданному селектору. То есть, если необходимо делегировано обрабатывать событие click на элементах списка, то следует делать это так:


 

Прямые обработчики в этой же ситуации устанавливались бы так:


 

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

3 комментария

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

      1. спасибо за ответ. с Datepicker решил тем ,что просто не стал его перерисовывать, вынеся за обновляемый блок. но стал другой вопрос динамически добавленных элементах. как получить данные из кода? например есть var $Container = $(«#container»); после обновления содержимого этого контейнера, который в середине обновляемого блока, как получить то, что в нем имеется, для последующего его использования? например хотя бы $Container.removeClass(«hidden»).

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *