Hello, everyone, I am autumn wind.

B: well… Here I go again, this time at… Nan Xi and the issues arising from the discussion.

So how did it go?

The cause of

Recently, Nanxi was reading articles related to the event and came to discuss with me that the execution effect of the following code was inconsistent with the article on the Internet. The code is as follows:

<div>
    <button>123</button>
</div>
<script>
  var btn = document.querySelector('button');
  var div = document.querySelector('div');
  btn.addEventListener('click', function () {
    console.log('bubble', 'btn');
  }, false);
  btn.addEventListener('click', function () {
    console.log('capture', 'btn');
  }, true);
  div.addEventListener('click', function () {
    console.log('bubble', 'div');
  }, false);
  div.addEventListener('click', function () {
    console.log('capture', 'div');
  }, true);
</script>

So that’s a very simple event registration code, and then we click button.

Let’s not look at the results, but think about it.

And then let’s look at the results

For most front-end veterans, the following sequence will come out of the mouth.

capture div
bubble btn
capture btn
bubble div

explore

But both MDN and most of the tutorials on the web are in that order.

I am puzzled by this phenomenon. I have a vague recollection that, a few months ago, Chrome did not behave this way. Is it because of the Chrome version?

The Chrome version of the GIF above is 90.0.4430.212

So I found a Chrome version of 84.0.4109.0 for testing.

As expected, there was a problem with the version, but it was still very difficult to track the matter. Searching the specification and checking some information on Google did not help me to solve this puzzle well. I am not sure whether it is because of the bug introduced by Chrome or some problems.

So I reported it to Chromium.

Eventually, with the help of the Chrome developers, these two discussions were found

https://github.com/whatwg/dom…

https://github.com/whatwg/dom…

Can see in the above issues, the cause is in https://bugs.webkit.org/show_… , someone pointed out that the current event model in WebKit would cause the capture event of the child element to be triggered before the capture event of the parent element in the case of Shadow DOM.

In the old model, once AT_TARGET was reached, all registered listeners were fired in order, regardless of whether they were marked for capture or not. Because the Shadow DOM creates multiple targets, the order of event execution is incorrect.

This problem works fine in Gecko, Mozilla Firefox’s typesetting engine (catch first, bubble later). For this reason WHATWG proposes a new model structure to solve this problem.

conclusion

All the questions have been solved, and now for us to sort out our problems.

1. According to the old version event triggering mechanism
performance The order in which the target element fires events is related to the order in which the events are registered
2. New event triggering mechanism
performance The target element firing sequence fires in the order of first capture and then bubble

The dividing line is between Chrome 89.0.4363.0 and Chrome 89.0.4358.0.

Chrome 89.0.4363.0 was released on 2020-12-22 in the last few months, so if you’ve updated Chrome in the last few months, you’re going to see the same thing I did.

In Chrome 89.0.4363.0 and later, the target element’s trigger order is no longer triggered in the registration order! Instead, follow the pattern of first capture and then bubble!

Then we’ll see how this changes for us.

  1. First of all, let’s make it clear that yes, most of the previous articles on the web are no longer applicable to the current version of Chrome!
  2. If there is a dependency related event firing sequence in our business, check it carefully!

An 🌰

<div>
    <button>123</button>
</div>
<script>
  var a = [];
  var btn = document.querySelector('button');
  var div = document.querySelector('div');
  btn.addEventListener('click', function () {
    console.log('bubble', 'btn');
    a.push(1);
  }, false);
  btn.addEventListener('click', function () {
    console.log('capture', 'btn');
    a.push(2);
  }, true);
  div.addEventListener('click', function () {
    console.log('bubble', 'div');
  }, false);
  div.addEventListener('click', function () {
    console.log('capture', 'div');
  }, true);
</script>

In the new version, when the button element is clicked, the final result of a is [2,1], whereas in the old version it was [1,2].

Then how to transform some online code at this stage?

The improved scheme

So now that we have no control over which version of the browser users use, how can we solve this problem to avoid online problems?

It’s really very simple.

To be compatible with this update, we simply need to write the capture event code first and then the bubble event code in the order of all the target element code.

thinking

Everything is not set in stone, and we should always take the relatively official articles or tutorials with a grain of salt and believe what we see. Perhaps my comments will be a wrong example in years to come, but they are a record of the problems of today. This article also has a lot of shortcomings, if you have any questions please point them out in the comments.

The resources

https://chromium.cypress.io/

https://github.com/whatwg/dom…

https://bugs.webkit.org/show_…

https://github.com/whatwg/dom…

https://dom.spec.whatwg.org/#…

conclusion

❤️ follow + thumb up + favorites + comments + forwarding, original is not easy, encourage the author to create better articles

Pay attention to the public number Qiufeng notes, a focus on the front-end interview, engineering, open source front-end public number