事件冒泡、事件捕获、事件委托

首先介绍个方法

element.addEventListener(event, function, useCapture)

addEventListener方法原生的JS方法,用来为一个特定的元素绑定一个事件处理函数。

三个参数分别:

  1. event: 事件类型
  2. function: 事件处理函数
  3. 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>
原文地址:https://www.cnblogs.com/Zzbj/p/15431038.html