事件冒泡、事件捕获、事件委托
首先介绍个方法
element.addEventListener(event, function, useCapture)
addEventListener方法原生的JS方法,用来为一个特定的元素绑定一个事件处理函数。
三个参数分别:
- event: 事件类型
- function: 事件处理函数
- useCapture: 控制事件阶段
第三个参数useCapture是boolean类型:
默认是false,表示在事件冒泡的阶段调用事件处理函数,
如果设置为 true,则表示在事件捕获的阶段调用事件处理函数。
事件冒泡
当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window。
即指子元素的事件向父元素传递的过程。
例如:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>事件冒泡</title> </head> <body> <div> <p> <button id="b1">点我</button> </p> </div> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script> /* 因为监听函数addEventListener第三个参数默认为false 因此直接使用click、focus等函数,默认就是冒泡事件 */ $('div').click(function () { console.log('我是div标签'); }); $('p').click(function () { console.log('我是一个p标签'); }); // $('#b1')[0] JQ原生转DOM元素 $('#b1')[0].addEventListener('click', function () { console.log('我是那个按钮!'); }, false) </script> </body> </html>
当点击按钮后,事件会从子元素(button)一直传递到父元素window,结果:
事件捕获
事件捕获与事件冒泡相反,事件的传递从父元素向下传递到子元素。
即指父元素的事件向子元素传递的过程。
例如:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>事件捕获</title> </head> <body> <div> <p> <button id="b1">点我</button> </p> </div> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script> // 设置为true代表事件捕获 $('div')[0].addEventListener('click', function () { console.log('我是div标签'); }, true); $('p')[0].addEventListener('click', function () { console.log('我是一个p标签'); }, true); // $('#b1')[0] JQ原生转DOM元素 $('#b1')[0].addEventListener('click', function () { console.log('我是那个按钮!'); }, true) </script> </body> </html>
当点击按钮后,事件会从父元素window一直传递到子元素(button),结果:
事件冒泡与事件捕获的关系
即:事件捕获先发生,再到事件冒泡
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>事件冒泡与捕获</title> </head> <body> <div> <p> <button id="b1">点我</button> </p> </div> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script> // 事件捕获 $('div')[0].addEventListener('click', function () { console.log('我是div标签'); }, true); // 事件冒泡 $('div')[0].addEventListener('click', function () { console.log('我是div标签'); }, false); $('p')[0].addEventListener('click', function () { console.log('我是一个p标签'); }, true); $('p')[0].addEventListener('click', function () { console.log('我是一个p标签'); }, false); $('#b1')[0].addEventListener('click', function () { console.log('我是那个按钮!'); }, true) $('#b1')[0].addEventListener('click', function () { console.log('我是那个按钮!'); }, false) </script> </body> </html>
当点击按钮后,先发生事件捕获,再发生事件冒泡,结果:
事件委托
事件委托是通过事件冒泡的原理,利用父标签去捕获子标签的事件。
语法: $("table").on("click", "button", function () { // JS代码 }) 解释:给table绑定一个点击事件,但是是通过button触发的。
注意事项1:
像click、keydown等DOM中定义的事件,我们都可以使用`.on()`方法来绑定事件,但是`hover`这种jQuery中定义的事件就不能用`.on()`方法来绑定了,
也就是说hover()方法不能直接使用事件委托,想使用事件委托的方式绑定hover事件处理函数,可以参照如下代码分两步绑定事件:
$('ul').on('mouseenter', 'li', function() {//绑定鼠标进入事件 $(this).addClass('hover'); }); $('ul').on('mouseleave', 'li', function() {//绑定鼠标划出事件 $(this).removeClass('hover'); });
注意事项2
关于this:谁触发这个事件,this就指向谁。
例如:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> </head> <body> <div id="div"> <p id="p"> <input type="button" value="点我" id="btn"> </p> </div> <script type="text/javascript"> $("#div").click(function () { //点击按钮,经过事件冒泡,触发这个事件 //此时this是代表div的,虽然点击的是那个按钮 //但是实际上是经过冒泡后,div自己触发的这个事件,所有this是div console.log(this); }); //任意注释一个script标签测试另一个标签 $("#div").on("click", "#btn", function () { //事件委托,给div绑定了一个事件,点击按钮触发这个事件 //此时this是代表按钮btn的,虽然绑定的事件是div //但是触发这个事件的是btn,所以this是btn console.log(this); }) </script> </body> </html>