Delegated event handler without jQuery

2020-04-16 04:06发布

问题:

Made this example: https://jsfiddle.net/d8ak0edq/2/

document.getElementById('outer').oncontextmenu = function() { return false; };

outer = document.getElementById('outer');
outer.addEventListener('mousedown', foo);
function foo(evt) {
  if (evt.which === 1) {
    evt.target.style.backgroundColor = 'red';
  } else if (evt.which === 3) {
    evt.target.style.backgroundColor = 'blue';
  }
}
/*
$outer = $('#outer');
$outer.on('mousedown', 'div', foo);
function foo(evt) {
  if (evt.which === 1) {
    $(this).css('background-color', 'red');
  } else if (evt.which === 3) {
    $(this).css('background-color', 'blue');
  }
} */
#outer {
  border: 2px solid black;
  width: 300px;
  height: 300px;
}
#inner {
  position: relative;
  left: 25%;
  top: 25%;
  border: 2px solid black;
  width: 150px;
  height: 150px;
}
<!doctype html>
<html class="no-js" lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
        <link rel="manifest" href="site.webmanifest">
        <link rel="apple-touch-icon" href="icon.png">
        <!-- Place favicon.ico in the root directory -->
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/main.css">
    </head>
    <body>
      <div id="outer">
        <div id="inner">
        
        </div>
      </div>


        <script src="js/vendor/modernizr-3.5.0.min.js"></script>
        <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
        <script>window.jQuery || document.write('<script src="js/vendor/jquery-3.2.1.min.js"><\/script>')</script>
        <script src="js/plugins.js"></script>
        <script src="js/main.js"></script>
    </body>
</html>

As you can see the jQuery has a nice way to do it, the 2nd parameter sets the 'target' and 'this' and if you click on the outer div nothing will happen even the event handler is on the outer div.

How do I make this without jQuery?

So by making the event handler on inner would obviously "fix" the problem, but I want that the event stays on the outer div but targets only inner, how to make this work (and not by adding && !(evt.target===outer))?

回答1:

The basic technique for delegation is: set a selectorable attribute on the inner, then attach event handler to the outer, then check for whether the event came from inner:

document.getElementById('outer').addEventListener('mousedown' function(outer_evt) {
    if (outer_evt.target.id == 'inner') {
        // I mousedowned on inner
    }
});

If you have other events attached to outer (this includes events attached to any ancestor of outer), and don't want them fired when you fire the inner event, use outer_evt.stopImmediatePropagation() and/or outer_evt.stopPropagation() (respectively).

If you want to refer to the element that the event bubbled up to, that's .currentTarget. (that is, above, outer_evt.currentTarget === document.getElementById('outer'))

See also EventTarget.addEventListener()