简体   繁体   中英

How to handle event delegation with priorities?

I have this look-a-like code in my app :

let item;

$('.parent').on('click', function () {
  item = $(this).attr('item') || 0; 
});

$('.parent').on('click', '.children', this, function () {
  doSomething();
});
<div class="parent" item="50">
  <div class="children">
  </div>
</div>

<div class="parent" item="51">
  <div class="children">
  </div>
</div>

<div class="parent" item="52">
  <div class="children">
  </div>
</div>

I have a parent element with several children in it. Clicking anywhere on the parent element will give me an item information, so I will be able to load functions according to this item variable on click on children.

My problem is : I have to delegate the onClick event on children to parent element otherwise the events will trigger in this order :

  1. Click on any child
  2. Click on parent, which is too late because I need item variable first

I have a functionality that replaces the parent element if activated, since it was dynamically inserted into the DOM, I have to delegate the onClick event as well, like this :

$('.grandParent').on('click', '.parent', function () {
  item = $(this).attr('item') || 0;
});

Now my problem is that the events are triggering in the wrong order again :

  1. Click on any child
  2. Click on parent

How can I manage to set click event on parent as top priority?

Edit :

I will be more specific. I have a messages list on my page, each .message element contains the message content but also some functionnalities like edit, delete, set as favorite, like, etc.

Like this :

<div class="message" data-item="1">
  <a class="edit">E</a>
  <a class="delete">X</a>
  <a class="favorite">Fav</a>
  <a class="like">Like</a>
  <div class="content">
    Hello world !
  </div>
</div>
<div class="message" data-item="2">
  <a class="edit">E</a>
  <a class="delete">X</a>
  <a class="favorite">Fav</a>
  <a class="like">Like</a>
  <div class="content">
    Hello world !
  </div>
</div>

Each one of those functionnalities will trigger different functions when clicked : edit(), delete(), like(), etc.

All of them will make AJAX requests which will then send the item variable to my server in order to know what item has to be impacted by this click.

To avoid repetition in my events handlers, I am trying to get the data-item attribute's value with one event bound to click on .message element, relying on the bubbling of children elements.

Get the item where you actually want it and get rid of the handler on parent :

$('.parent').on('click', '.children', function () {
  item = $(this).closest('.parent').attr('item');
  doSomething();
});

EDIT:

Then get the item when you click on the grandparent:

$('.grandParent').on('click', '.children', function () {
  item = $(this).closest('.parent').attr('item');
});

EDIT #2:

Based on the OPs updated requirements, do it like this:

<div class="message" data-item="1">
  <a class="action edit" data-type="edit">E</a>
  <a class="action delete" data-type="delete">X</a>
  <a class="action favorite" data-type="favorite">Fav</a>
  <a class="like">Like</a>
  <div class="content">
    Hello world !
  </div>
</div>
<div class="message" data-item="2">
  <a class="action edit" data-type="edit">E</a>
  <a class="action delete" data-type="delete">X</a>
  <a class="action favorite" data-type="favorite">Fav</a>
  <a class="like">Like</a>
  <div class="content">
    Hello world !
  </div>
</div>

$(document).on('click','.message .action',function(e) {
   const item = $(this).closest('message').attr('item');
   switch($(this).data('type')) {
     case 'edit': doEdit(item); break;
     case 'delete': doDelete(item); break;
     case 'favorite': doFavorite(item); break;
   }
});

See, one event handler?

It's a very common pattern to do what you're doing. In the absence of a more robust framework (eg React), then using plain jQuery this is how it should be done.

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