问题
I've got a people search script that displays suggestions as you type. The structure for the results is loosely this:
<div id="peopleResults">
<div class="resultHolder">
<div data-userid="ABC123" class="person">
<div class="name">Last, First</div>
<div class="title">Job Title</div>
<a class="email" href="mailto:person@company.com">person@company.com</a><span class="phone">12345</span>
</div>
<!-- more people... -->
</div>
</div>
Since the list of people gets altered as you type, up until now I was using JQuery's live() function to automatically bind click events to all the .person elements. This is deprecated and bad practice, so I'm trying to update the code.
I see that I could use something like:
$('#peopleResults').on('click', '.person', function(){
// handle the click
})
But I want to understand a bit more about how to handle this in vanilla javascript. I THOUGHT that when clicking on the child of an item with a click event, the event would "bubble" up through the elements, and I could catch it when it hit the .person element. Excuse the sloppy code, but something like:
document.getElementById('peopleResults').addEventListener('click', function(e){
if(e.target.classList.contains('person')) {
// handle click
}
});
I've done similar things in the past, but usually with links. (.person can't be a link in this case because it contains an email link.)
So in this case it doesn't work. If I click on .name within .person, the target is .name.
This seems like something fundamental that just isn't clicking in my brain. What's the typical way to handle this in JavaScript?
回答1:
You can set pointer-events to none
for all children of the desired targets:
.person > * {
pointer-events: none;
}
This way event.target
will be a .person
element instead of one of its descendants.
document.getElementById('peopleResults').addEventListener('click', function(e){
if(e.target.classList.contains('person')) {
alert('Person clicked');
}
});
.person > * {
pointer-events: none;
}
<div id="peopleResults">
<div class="resultHolder">
<div data-userid="ABC123" class="person">
<div class="name">Last, First</div>
<div class="title">Job Title</div>
<a class="email" href="mailto:person@company.com">person@company.com</a><span class="phone">12345</span>
</div>
<!-- more people... -->
</div>
</div>
Note that this approach will break the functionality of interactive elements (such as links) inside .person
.
回答2:
When using jQuery events you are given two properties which you should be familiar with:
target
currentTarget
when using event delegation (meaning catching events on a parent element) target
will be the element which initially triggered the event while currentTarget
will be the element which catches the event.
Consider this code example:
$('#peopleResults').on('click', '.person', function(e) {
if ($(e.currentTarget).hasClass('person')) console.log('yay!');
});
P.S. - when not using event delegation both properties should point to the same element.
For more info about currentTarget.
来源:https://stackoverflow.com/questions/27275279/event-on-parent-click-child-event-bubbling