Search code examples
javascripthtmleventscapture

The executing order of capture and bubble for two same listeners in js


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>capture and bubble</title>
  <style type="text/css">
  #child{
    background: red;
    width:50px;
    height:50px;
  }
  #father{
    width:100px;
    height:100px;
    background:green;
  }
  </style>
</head>
<body>
    <div id='father'>
      <div id='child'></div>
    </div>
</body>
<script type="text/javascript">
  var parent = document.getElementById("father");
  var child = document.getElementById('child');
  var html = document.getElementsByTagName("html")[0];
  var body = document.body;
  parent.addEventListener("click",function() {
    console.log("I am capturing parent");
  },true);
   parent.addEventListener("click",function() {
    console.log("I am parent");
  },false);
   child.addEventListener("click",function() {
    console.log("I am capturing child");
  },true);
  child.addEventListener("click",function() {
    console.log("I am child");
  },false);
  body.addEventListener("click",function() {
    console.log("I am capturing body");
  },true);  
  body.addEventListener("click",function() {
    console.log("I am body");
  },false);
  html.addEventListener("click",function() {
    console.log("I am capturing html");
  },true);
  html.addEventListener("click",function() {
    console.log("I am html");
  },false);
  parent.addEventListener("click",function() {
    console.log("I am capturing parent");
  },true);
   parent.addEventListener("click",function() {
    console.log("I am parent");
  },false);
</script>
</html>

For the above html containning a js to display executing order of capture and bubble,i have binded two listeners of capture and bubble two times for the parent(div father),one pair of capture and bubble for the parent(div father) is from 5th line till 10th line in the js script part; other pair of capture and bubble for the parent(div father) is at the ending of the js script part.

Click the green div(father div),get the result in console.

test.html:50 I am capturing html
test.html:44 I am capturing body
test.html:32 I am capturing parent
test.html:35 I am parent
test.html:56 I am capturing parent
test.html:59 I am parent
test.html:47 I am body
test.html:53 I am html

Why the result is not the following?

test.html:50 I am capturing html
test.html:44 I am capturing body
test.html:32 I am capturing parent
test.html:56 I am capturing parent
test.html:35 I am parent
test.html:59 I am parent
test.html:47 I am body
test.html:53 I am html

Please explain it in detail.


Solution

  • The MDN documentation for addEventListener states:

    Note: For event listeners attached to the event target, the event is in the target phase, rather than the capturing and bubbling phases. Events in the target phase will trigger all listeners on an element in the order they were registered, regardless of the useCapture parameter.

    This is what happens here. The event listeners are attached to the event target (parent in your example), therefore the event is in the target phase and the listeners are triggered in the order they were registered.

    Note that if you click child, this doesn't happen because the event is in capture or bubbling phase. The result as expected is:

    I am capturing html
    I am capturing body
    I am capturing parent
    I am capturing parent
    I am capturing child
    I am child
    I am parent
    I am parent
    I am body
    I am html
    

    There is a good explanation and diagram of the event flow here.

    enter image description here