浅析DOM事件模型

336 阅读2分钟

本文中的DOM事件模型为DOM level 2模型(W3C标准模型),现代浏览器均支持此模型。

事件捕获与冒泡

该事件模型中,一次事件共有三个过程:

  • 捕获阶段(Capture Phase):事件从Window对象开始到目标元素的父元素(由外到内)。
  • 目标阶段(Target Phase):事件到达目标元素。
  • 冒泡阶段(Bubbling Phase):事件从目标元素的父元素到Window对象(由内到外)。 事件模型

此过程可以通过以下代码来体现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM</title>
    <style media="screen">
        #div {
            width: 300px;
            height: 100px;
            background: blue;
            color: #fff;
            text-align: center;
            line-height: 100px;
        }
    </style>
</head>

<body>
    <div id="div">
        点击目标元素触发事件
    </div>
    <script type="text/javascript">
        let div = document.querySelector('#div')
        //捕获阶段事件函数
        const f1 = function (e) {
          console.log('捕获Captrue ' + this.toString());
        }
        //冒泡阶段事件函数
        const f2 = function (e) {
            console.log('冒泡Bubbling ' + this.toString());
        }


        //捕获阶段监听函数

        div.addEventListener('click', f1, true);//目标元素监听函数

        window.addEventListener('click', f1, true); //window节点监听函数

        document.addEventListener('click', f1, true); //document节点监听函数

        document.documentElement.addEventListener('click', f1, true); //html节点监听函数

        document.body.addEventListener('click', f1, true); //body节点监听函数

        //冒泡阶段监听函数

        div.addEventListener('click', f2); //目标元素监听函数

        window.addEventListener('click', f2); //window节点监听函数

        document.addEventListener('click', f2); //document节点监听函数

        document.documentElement.addEventListener('click', f2); //html节点监听函数

        document.body.addEventListener('click', f2); //body节点监听函数
    </script>
</body>

</html>

从下图可较清晰的看到事件模型的处理过程:

运行结果

trap: 当在目标阶段触发多个监听事件时,此时没有捕获与冒泡之分,而是根据监听器绑定的顺序来依次执行。

事件监听函数

addEventListener():用于为元素添加事件监听

element.addEventListener(eventType, function, useCapture);

参数:

  • 第一个为监听的事件的类型,如clickmousedown
  • 第二个为事件出发后调用的函数
  • 第三个参数类型为布尔值,表示为该事件监听用于冒泡阶段还是捕获阶段,true表示捕获,false表示冒泡,默认值为false,即默认为冒泡阶段

Event对象

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。event对象作为触发事件时执行回调函数的传入参数。

一些属性与方法:

  1. event.target

    event.target 属性返回触发/产生/生成事件的元素。可理解为用户操作的元素。

  2. event.currentTarget

    event.currentTarget 属性是在事件所绑定的元素。可理解为监听器所在的元素。一般this为event.currentTarget,但不推荐用this来代替,使用属性可读性更佳。

  3. event.stopPropagation()

    此方法可阻止当前事件继续进行捕捉(capturing)及冒泡(bubbling)阶段的传递。

    dom.addEventListenner('click',function(event){
    	event.stopPropagation(); //事件不再继续传递
    })
    
  4. event.preventDefault()

    如果事件可以被取消,就取消事件(即取消事件的预设/默认行为)。但不会影响事件的传递,事件仍会继续传递。

    a.addEventListenner('click',function(event){
    	event.preventDefault(); //阻止a标签的默认跳转事件
    })
    

tip: event.target指向触发事件的元素。 event.currentTarget指向监听事件的元素。