# DOM操作之事件传播

作者: 多叉树;转载须注明出处

Untitled

如上图,我们用DIV创建了三个盒子,然后每个盒子设置一个监听点击事件, 如果我们点击三个盒子的共同区域, 那么他们是不是都会执行,如果会,他们的执行顺序是什么?

我们使用上节的监听事件来做个例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件传播</title>

    <style>
        #box1 {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
            padding: 50px;
        }

        #box2 {
            width: 200px;
            height: 200px;
            border: 1px solid #000;
            padding: 50px;
        }

        #box3 {
            width: 100px;
            height: 100px;
            border: 1px solid #000;
            padding: 50px;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>

    <script>
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');
    
        box1.onclick = function() {
            console.log('box1 click');
        }

        box2.onclick = function() {
            console.log('box2 click');
        }

        box3.onclick = function() {
            console.log('box3 click');
        }

    </script>
</body>
</html>

如果我们运行上面的程序,我们会感觉事件的传播时从内到外的。

实际上,事件的传播顺序: 先从外到内,然后在从内到外

Untitled

事件的传播分可以简单分为两个阶段

  • 捕获阶段:事件从window对象向下传播到目标元素
  • 冒泡阶段:事件到达目标元素后再依次向上传递

onXXX 写法只能监听冒泡阶段,我们以为事件的传递时从目标元素开始向上传递的,其实只是这种写法的局限性而已(事实上我们也很少监听捕获)。

# addEventListener

我们还有一种事件监听的方法, 他可以根据需要监听冒泡阶段还是监听

oBox.addEventListener = function('click', function(){
	// 事件处理函数主体
}, true); // true表示监听捕获阶段 false 监听冒泡阶段

示例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件传播</title>

    <style>
        #box1 {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
            padding: 50px;
        }

        #box2 {
            width: 200px;
            height: 200px;
            border: 1px solid #000;
            padding: 50px;
        }

        #box3 {
            width: 100px;
            height: 100px;
            border: 1px solid #000;
            padding: 50px;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>

    <script>
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');
    

        box1.addEventListener('click', function(){
            console.log('我是box1的捕获阶段');
        }, true)

        box2.addEventListener('click', function(){
            console.log('我是box2的捕获阶段');
        }, true)

        box3.addEventListener('click', function(){
            console.log('我是box3的捕获阶段');
        }, true)

        box1.addEventListener('click', function(){
            console.log('我是box1的冒泡阶段');
        }, false)

        box2.addEventListener('click', function(){
            console.log('我是box2的冒泡阶段');
        }, false)

        box3.addEventListener('click', function(){
            console.log('我是box3的冒泡阶段');
        }, false)

    </script>
</body>
</html>

# 重复执行问题

我们学了两个监听事件的方法。 onX() 方法 和 addEventListener , 如果设置多个相同类型的事件, 会怎么样?

onX 的从写法上也会看的出来, 后写的方法会覆盖前面的,所以重复写很多次,也只会执行最后的一次监听使事件

而addEventListener 则会执行多次

举例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件传播</title>

    <style>
        #box1 {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
            padding: 50px;
        }

        #box2 {
            width: 200px;
            height: 200px;
            border: 1px solid #000;
            padding: 50px;
        }

        #box3 {
            width: 100px;
            height: 100px;
            border: 1px solid #000;
            padding: 50px;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>

    <script>
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');
   
             
        box2.onclick = function(event){
            alert('B');
        }

        box2.onclick = function(event){
            alert('B');
        }

        box2.addEventListener('click', function(){
            alert('C');
        }, false)

        box2.addEventListener('click', function(){
            alert('D')
        }, false)

</script>
</body>
</html>