В случае делегированных обработчиков событий, где у вас может быть что-то вроде этого:
<ul>
<li data-id="1">
<span>Item 1</span>
</li>
<li data-id="2">
<span>Item 2</span>
</li>
<li data-id="3">
<span>Item 3</span>
</li>
<li data-id="4">
<span>Item 4</span>
</li>
<li data-id="5">
<span>Item 5</span>
</li>
</ul>
и ваш код JS так:
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target),
itemId = $target.data('id');
//do something with itemId
});
});
Вы, скорее всего, обнаружите, что itemId есть undefined
, поскольку содержимое LI обернуто в a <span>
, что означает, что <span>
, вероятно, будет целью события. Вы можете обойти это с небольшой проверкой, например, так:
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target).is('li') ? $(event.target) : $(event.target).closest('li'),
itemId = $target.data('id');
//do something with itemId
});
});
Или, если вы предпочитаете максимизировать удобочитаемость (а также избежать ненужного повторения вызовов JQuery):
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target),
itemId;
$target = $target.is('li') ? $target : $target.closest('li');
itemId = $target.data('id');
//do something with itemId
});
});
При использовании делегирования события .is()
метод имеет неоценимое значение для проверки того, что ваша цель события (помимо всего прочего) - это именно то, что вам нужно. Используйте .closest(selector)
для поиска по дереву DOM и используйте .find(selector)
(обычно в сочетании с .first()
, как в .find(selector).first()
) для поиска по нему. Вам не нужно использовать .first()
при использовании .closest()
, так как он возвращает только первый соответствующий элемент-предок, а .find()
возвращает все соответствующие потомки.