JavaScript 事件委托、冒泡和捕获之间有什么区别?
***
事件委托是一种技术,冒泡是事件本身所做的,而捕获是对不冒泡的事件使用事件委托的一种方式。
事件委托#
事件委托是一种侦听事件的技术,您可以将父元素委托为其中发生的所有事件的侦听器。
我经常以监听所有点击document
为例,但它可以是页面上的任何元素。
例如,如果您想检测特定表单中任何字段的值发生变化的任何时间,您可以这样做:
var form = document.querySelector('#hogwarts-application'); // Listen for changes to fields inside the form form.addEventListener('input', function (event) { // Log the field that was changed console.log(event.target); }, false);
事件冒泡#
冒泡是事件本身所做的。
如果您曾经看过一杯苏打水中的气泡,您就会明白事件冒泡是如何工作的。
事件开始是触发它的元素(也就是说,#email
在我们上面的示例中更改字段)。然后,它会冒泡到它的每个父元素,直到它到达该html
元素。
以表单字段为例,事件将冒泡到父表单,然后是表单所在的任何容器或 div,然后是body
,然后是html
元素,然后是document
,然后是window
。
任何这些父元素上的任何侦听器都会在冒泡时被触发。
html
<main> <section> <article> <div> <form> <label for="name">Your Name</label> <input type="text" name="name" id="name"> </form> </div> </article> </section> </main>
js
var logEvent = function (event) { console.log(event.target); }; document.querySelector('main').addEventListener('input', logEvent, false); document.querySelector('section').addEventListener('input', logEvent, false); document.querySelector('article').addEventListener('input', logEvent, false); document.querySelector('div').addEventListener('input', logEvent, false); document.querySelector('form').addEventListener('input', logEvent, false); document.querySelector('input').addEventListener('input', logEvent, false);
事件捕获#
大多数事件都是冒泡的。但有些,比如focus
事件,没有。
document.addEventListener('focus', function (event) { console.log(event.target); }, false);
您可以一遍又一遍地专注于事情,但事件回调永远不会运行。
不过,您可以使用一个技巧来捕获事件。中的最后一个参数addEventListener()
称为useCapture
。我们几乎总是将其设置为 false。
对于不冒泡true
的事件,请将其设置为无论如何捕获事件。
更新例子,变成捕获
document.addEventListener('focus', function (event) { console.log(event.target); }, true);
捕获完整演示
<form> <label for="name">Your Name</label> <input type="text" name="name" id="name"> </form>
document.addEventListener('focus', function (event) { console.log(event.target); }, true);