简体   繁体   中英

How to capture an event in the middle

I would like to attach a click event listener and run some action with "data-attr" at this context, as elegant as possible.

<div id="container">

    <div class="group" data-attr="info1">
        <div class="a-casual-class-1">***</div>
        <div class="a-casual-class-2">AAA</div>
    </div>

    <div class="group" data-attr="info2">
        <div class="a-casual-class-1">***</div>
        <div class="a-casual-class-2">AAA</div>
    </div>

</div>

A) Just a single event to the root (#container)

  • check if event.target is a-casual-class-1 or a-casual-class-2 and get parent element to retrieve the data attribute or
  • retrieve the .group element from the root and the data-attr.

B) I could get first the nodes list of '.group', make a loop and attach the event listener to each element.

Is there a better approach to handle this situation?

A) Just a single event to the root (#container)

You can use document.querySelectorAll() to target all the internal divs.

B) I could get first the nodes list of '.group', make a loop and attach the element.

When you make a selector it will give you an array like object of dom nodes. You have to loop through them and bind the events.

So the overall idea is, as events are tend to bubble up in the DOM, you can bind the event on the #container 's child divs. Now whenever you click on the child divs of .group it will always find the div which got the event bound and just executes the callback.

 var divs = document.querySelectorAll('#container > div'); // divs.forEach(function(div){ // it worked at chrome 57 [].forEach.call(divs, function(div){ // changed if user is on old version of browser div.addEventListener('click', function(e){ var data = this.dataset.attr; console.log(data); }); }); 
 <div id="container"> <div class="group" data-attr="info1"> <div class="a-casual-class-1">***</div> <div class="a-casual-class-2">AAA</div> </div> <div class="group" data-attr="info2"> <div class="a-casual-class-1">***</div> <div class="a-casual-class-2">AAA</div> </div> </div> 

A) Just a single event to the root (#container)

If the structure is not too complex, then you could bind the event to the root and check the class of event.target to run your action.

check if event.target is a-casual-class-1 or a-casual-class-2 and get parent element to retrieve the data attribute or retrieve the .group element from the root and the data-attr.

Instead of checking for a-casual-class-1 , you could check for the parent's class and then take the action.

For Example:

 var target = document.getElementById('container'); target.addEventListener('click', doAction); function doAction(e) { if (e.target.className === 'group') { console.log(e.target.dataset.attr); } if (e.target.parentElement.className === 'group') { console.log(e.target.parentElement.dataset.attr); } } 
 #container { margin: 12p; padding: 12px; border: 4px solid #b33; } .group { margin: 12px; padding: 12px; border: 4px solid #33b; } .group > div { background-color: #ddd; } 
 <div id="container"> <div class="group" data-attr="info1"> <div class="a-casual-class-1">***</div> <div class="a-casual-class-2">AAA</div> </div> <div class="group" data-attr="info2"> <div class="a-casual-class-1">***</div> <div class="a-casual-class-2">AAA</div> </div> </div> 

B) I could get first the nodes list of '.group', make a loop and attach the event listener to each element.

If your markup and structure gets complex, then it would be better to iterate through your .groups using querySelectorAll and then bind the event to each one of those. This is what is shown in the other answer.


Bottomline: Just see if your code starts getting too complex depending on the complexity of your markup structure. Also, you need to consider if you have other event handlers bound to the siblings and/or children nested in the #container . In that case, you might find yourself fiddling with capture and/or stopPropagation .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM