Pull to refresh

Еще раз о делегирование или как правильно использовать свои события

Reading time3 min
Views18K
В этом посте хочу еще раз подчеркнуть механизм работы делегирования и использование собственных событий, чтобы избежать ошибок с которыми мне пришлось столкнутся.

Для начала вспомним, что же такое делегирование на следующем примере:

<div id=«container»>
  <a href="" class=«edit»>Edit</a>
  <a href="" class=«delete»>Delete</a>
</div>

<script type=«text/javascript»>
  $('#container').click(function(event) {
    var elem = $(event.target);

    if (elem.hasClass('edit')) {
      console.info('Clicked to edit link');
    }
    else if (elem.hasClass('delete')) {
      console.info('Clicked to delete link');
    }

    return false;
  });
</script>


В примере есть две ссылки, по клику на которые выполнятся те или иные действия. В данном случае это редактирование и удаление item. Для того, чтоб не добавлять соответствующие слушатели на каждую из ссылок, можно просто добавить один слушатель для контейнера, в котором находятся ссылки и дальше уже по событию получить элемент с которым было связанно это событие. Т.е. в данном примере по клику на одну из ссылок мы получим элемент на который был произведен клик и определим какой из ссылок принадлежит это событие. Кликнув на ссылку 'Edit', в консоли выведется сообщение 'Clicked to edit link', а для ссылки ‘Delete’ — 'Clicked to delete link’.

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

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

<div id=«container»>
    <div id=«subcontainer»></div>
</div>

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

<div id=«container»>
    <div id=«subcontainer»></div>
</div>

<script type=«text/javascript»>
    $(document).ready(function() {
      $('#container').bind('some_event', function() {
        console.info('worked event for container');
      });

      $('#subcontainer').bind('some_event', function() {
        console.info('worked event for subcontainer');
      });

      $('#subcontainer').trigger('some_event');
    });
</script>

В этом примере мы просто добавляем слушателя родительскому контейнеру и отслеживаем событие 'some_event'. То же самое делаем и для вложенного контейнера 'subcontainer'. Если в данный момент вызвать триггер для вложенного контейнера, то в консоли у нас выведется:

worked event for container
worked event for subcontainer

Если честно, когда я добавлял, у себя в проекте слушателей для одинаковых событий, к подобной структуре, то я такого результата не ожидал. События у меня именовались одинаково, да вот тока выполняли совсем разные действия. Когда код такой вот небольшой, то ошибку можно найти сразу, а если это все находится в классах по несколько 100 строк, то очень такие не просто отследить не правильный код. Чтоб избежать ошибки в выполнении, лучше всегда использовать namespaces.

<script type=«text/javascript»>
    $(document).ready(function() {
      $('#container').bind('some_event.container', function() {
        console.info('worked event for container');
    });

      $('#subcontainer').bind('some_event.subcontainer', function() {
        console.info('worked event for subcontainer');
    });

      $('#subcontainer').trigger('some_event.subcontainer');
    });
</script>

Надеюсь этот пост поможет избежать ошибок в коде, с которыми мне пришлось столкнутся, при использовании собственных событий.
Tags:
Hubs:
+17
Comments28

Articles

Change theme settings