25.07.2017, 22:56
|
Новичок на форуме
|
|
Регистрация: 25.07.2017
Сообщений: 9
|
|
Назначение обработчиков и SPA
Доброго времени.
Нужен совет от гуру.
Сразу скажу, что с web-разработкой знаком давно. Но что касается webА, то работал преимущественно с php. На js тоже успешно пишу, но не считаю его основным языком. Так что белых пятен хватает.
Задача следующая: требуется написать сайтик, но сайт должен представлять собой SPA. Никаких перезагрузок страниц, всё исключительно на ajaxЕ со всеми вытекающими и т.д.
Стоит отметить, что предполагается достаточно большое количество страниц. На каждой странице большое количество элементов взаимодействия с пользователем: ссылочки, кнопочки, формочки... Страницы, как правило, неоднотипные. Т.е. каждая страница, кроме пары блоков, не похожа на любую другую.
И тут меня начинают мучать сомнения. Как же наиболее эффективно организовать назначение обработчиков на события.
Рассматривается два варианта.
Первый.. Делегирование. На какой-то общий элемент (контейнер) навесить все обработчики.
Второй.. Навешивать обработчики через атрибуты элементов.
Всегда придерживался правила не смешивать html и js. С этой позиции делегирование представляется более правильным. Но не будет ли это слишком накладно в данном конкретном случае? Ведь когда внутри контейнера у нас произойдёт, скажем, клик, то у нас же запустятся все обработчики данного события на контейнере. А их будет много.
Вариант с атрибутами кажется менее накладным, но как-то и нравится меньше. Менее красиво что ли...
В общем, готов выслушать мнение сообщества.
Заранее благодарю.
|
|
26.07.2017, 05:18
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от GeekHacker
|
Ведь когда внутри контейнера у нас произойдёт, скажем, клик, то у нас же запустятся все обработчики данного события на контейнере.
|
С чего вдруг? Два элемента А и В делегируют обработку щелчка родителю. Если щелкнули по В, то родителем будет обработан щелчок именно по нему, а не по А, так у него событие "автоматом" не возникнет. Кроме того можно использовать пространство имен.
|
|
26.07.2017, 10:19
|
Новичок на форуме
|
|
Регистрация: 25.07.2017
Сообщений: 9
|
|
ну почему же? Есть два элемента с id a и с id b внутри родителя с id d.
Мы хотим обрабатывать клики на a и b через делегирование. Для чего вешаем два обработчика на d.
При клике на любой из элементов будут запускаться оба обработчика.
Другое дело, что внутри обработчиков мы вычисляем event.target и полезный код будет выполнен только в случае, если event.target тот, что нам нужен, но это не отменяет того факта, что запустятся оба обработчика.
Топорный пример
var x = 2;
document.addEventListener('DOMContentLoaded', function(){
//первый обработчик
document.getElementById('d').addEventListener('click', function(event){
x++;
var target = event.target;
while(target != this){
if(target.id == 'a'){
alert('Вы кликнули по элементу с ID "a"');
return;
}
else
target = target.parentNode;
}
});
//второй обработчик
document.getElementById('d').addEventListener('click', function(event){
x++;
var target = event.target;
while(target != this){
if(target.id == 'b'){
alert('Вы кликнули по элементу с ID "b"');
return;
}
else
target = target.parentNode;
}
});
});
По клику на любом элементе мы увидим сообщение (одно), т.к. определив event.target мы всё правильно разрулили, но значением переменной x будет 2. Т.к. оба обработчика инкрементировали предыдущее её значение.
Да, можно было бы повесить один обработчик и в условиях зависимо от event.target всё разруливать, но это вообще не вариант. Т.к. логики будет много и там запутаться можно будет.
|
|
26.07.2017, 10:32
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от GeekHacker
|
При клике на любой из элементов будут запускаться оба обработчика.
|
С чего вдруг, если событие одно, а делегирование, это определение источника события?
|
|
26.07.2017, 11:14
|
Новичок на форуме
|
|
Регистрация: 25.07.2017
Сообщений: 9
|
|
Ну хотябы потому, что в данном случае мы вешаем на один элемент два обработчика события click. Разве нет? Запустите код из примера и посмотрите сами.
|
|
26.07.2017, 11:18
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(function() {
$('div').on('click', 'a', function(e) {
alert(e.target.tagName)
});
$('div').on('click', 'span', function(e) {
alert(e.target.tagName)
});
});
</script>
</head>
<body>
<div>
<a>A</a>
<span>Span</span>
</div>
</body>
</html>
Проверяйте, у каждого элемента будет свой обработчик, хотя делегируют они его одному родителю. При делегировании будет определяться источник события, в этом вся соль.
|
|
26.07.2017, 13:17
|
Новичок на форуме
|
|
Регистрация: 25.07.2017
Сообщений: 9
|
|
А я разве утверждаю обратное?
Но если уж придираться к мелочам, то у дочерних элементов вообще нет обработчиков. Все обработчики мы вешаем на родителя. И срабатывают они на родителе. и при возникновении события сработает их столько, сколько мы их повесили на родителя.
А вся эта магия с делегированием работает исключительно благодаря тому, что события могут всплывать по структуре DOM. и что в объекте события нам доступен реальный источник события. Разница между target и currentTarget.
event.target - элемент на котором произошло событие и от которого оно начало всплытие.
event.currentTarget - элемент, на котором сработал обработчик события.
Я специально не стал использовать в примере какие-либо библиотеки типа JQuery, т.к. получается менее наглядно.
Берите мой пример и при помощи контрольной переменной смотрите сколько было срабатываний обработчиков при клике на любом из дочерних элементов.
|
|
26.07.2017, 13:34
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от GeekHacker
|
И срабатывают они на родителе. и при возникновении события сработает их столько, сколько мы их повесили на родителя.
|
С чего вдруг при щелчке на одном элементе, возникнут щелчки на всех других дочерних?
В голове что-то не укладывается. Хрен с ним, пусть будет так:
$a = [
'a' => function() {},
'b' => function() {}
]
Если $a['b'](), то означает ли, что при этом будет выполнено и $a['a']()? А почему при щелчке по Span должен выполняться и обработчик А?
О чем речь?
|
|
26.07.2017, 13:48
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
GeekHacker,
доперло что не нравится - цена метода?
|
|
26.07.2017, 14:25
|
Новичок на форуме
|
|
Регистрация: 25.07.2017
Сообщений: 9
|
|
А причём тут дочерние?
Речь о том, что событие возникает на родителе. С этим вы же спорить не будете? Всплытие ведь. А на родителе у нас висит два обработчика. Вот они и срабатывают.
Ещё раз, берите мой пример и смотрите как работают обработчики. Какое сообщение мы получим в алерте и каким станет значение x после клика на любом потомке.
|
|
|
|