En el caso de los controladores de eventos delegados, donde podría tener algo como esto:
<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>
y tu código JS así:
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target),
itemId = $target.data('id');
//do something with itemId
});
});
Lo más probable es que encuentre ese itemId undefined
, ya que el contenido del LI está envuelto en un <span>
, lo que significa <span>
que probablemente será el objetivo del evento. Puede solucionar esto con un pequeño cheque, así:
$(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
});
});
O, si prefiere maximizar la legibilidad (y también evitar la repetición innecesaria de llamadas de ajuste 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
});
});
Cuando se utiliza la delegación de eventos, el .is()
método es invaluable para verificar que el objetivo de su evento (entre otras cosas) sea realmente lo que necesita. Use .closest(selector)
para buscar el árbol DOM y use .find(selector)
(generalmente junto con .first()
, como en .find(selector).first()
) para buscarlo. No es necesario usar .first()
cuando se utiliza .closest()
, ya que sólo devuelve el primer elemento antecesor juego, mientras que .find()
los retornos todos los descendientes coincidentes.