简易全栈

一片文章读懂DOM事件模型

2018-03-29  本文已影响89人  Mr_Alpha

DOM事件模型

  1. 从技术上来说,W3C的DOM标准并不支持上述最原始的添加事件监听函数的方式,这些都是在DOM标准形成前的事件模型。尽管没有正式的W3C标准,但这种事件模型仍然得到广泛应用,这就是我们通常所说的0级DOM。
<input type="button" id="myButton" onclick="alert('Button Click')" />   
或
document.getElementById("myButton").onclick = function () {  
    alert("Button Click");  
}   
  1. 没有1级DOM。DOM级别1于1998年10月1日成为W3C推荐标准。1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。
  2. 在2级DOM中除了定义了一些DOM相关的操作之外还定义了一个事件模型 ,这个标准下的事件模型就是我们所说的2级DOM事件模型。
document.getElementById("myButton").addEventListener("click",
        function (event) {
            alert("Button Click");
            console.log(event)
        },
        true)
        // 回调的第一个参数是被触发的事件对象,下面会简单介绍Event

DOM事件流

描述的就是从页面中接受事件的顺序。分有事件冒泡与事件捕获两种。
DOM事件流有三个阶段:

  1. 事件捕获阶段
  2. 处于目标阶段
  3. 事件冒泡阶段
DOM事件流

可以通过addEventListener注册事件时声明捕获还是冒泡阶段,处于捕获阶段的事件会比冒泡阶段先发生

相关API

  1. Event(typeArg, eventInit)
    1. type
    2. target
    3. currentTarget
    4. clientX, clientY
    5. screenX, screenY
  2. CustomEvent(typeArg, eventInitDict)
  3. addEventListener
    1. 注册事件监听器
    2. 常用格式target.addEventListener(type, listener, useCapture)
    3. 回调listener的第一个参数可以是event对象
    4. useCapture表示注册的是捕获阶段(true)还是冒泡阶段(false,默认)
  4. stopPropagation,阻止事件传递
  5. preventDefault,阻止事件默认行为,下面两个例子
    1. 阻止复选框被勾选
    2. 阻止input写入内容

简单说一下,Event的eventInit和CustomEvent的eventInitDict的区别
Event的eventInit有三个属性可以选择:bubbles表示是否可以冒泡,cancelable表示是否可以被取消,还有一个不常用的composed;
CustomEvent的eventInitDict,除了上面的bubbles和cancelable,还有一个details,它可以传入你自定义的一些数据,供给注册事件监听器时在回调里面可以调用的一些数据

重点解析

bubbles

默认为false,当为false时不发生事件冒泡,也就是说,如果注册的事件监听器是冒泡阶段捕获的话,将不会发生

var button = document.getElementById('clickMe');

    var myEvent = new CustomEvent('demoEvent', {
        bubbles: false,
        cancelable: false,
        detail: {
            index: 'hello demo'
        }
    })

    button.addEventListener('click', function () {
        console.log('1. You click Button')
        button.dispatchEvent(myEvent)
    }, true);

    document.body.addEventListener('demoEvent', function () {
        console.log('2. You click body')
    }, false);

    document.addEventListener('demoEvent', function (e) {
        console.log('3. You click document')
    }, true);

    window.addEventListener('demoEvent', function (e) {
        console.log('4. You click window')
    }, false);

上面的2和3不会发生,因为事件demoEvent的bubbles是false,事件没有冒泡阶段

cancelable

如果该事件的 cancelable 属性为 false, 则该事件的监听器无法阻止默认行为, 调用preventDefault() 将产生错误

自定义事件

逻辑如下:

  1. 新建一个事件对象,Event或者CustomEvent都行,但是变量名不要取event,因为在回调里会因为作用域问题被屏蔽
  2. 用一个节点对象发起事件(dispatch),该节点就算是事件流里的目标对象
  3. 在事件流里的所有注册了该事件的节点对象,都会调用回调
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Event Bubbling</title>
</head>

<body>
    <button id="clickMe">Click Me</button>
</body>

</html>
<script>
    var button = document.getElementById('clickMe');

    var myEvent = new CustomEvent('demoEvent', {
        bubbles: true,
        cancelable: false,
        detail: {
            index: 'hello demo'
        }
    })

    button.addEventListener('click', function () {
        console.log('1. You click Button')
        button.dispatchEvent(myEvent)
    }, true);

    document.body.addEventListener('demoEvent', function () {
        console.log('2. You click body')
    }, false);

    document.addEventListener('demoEvent', function (e) {
        console.log('3. You click document')
    }, true);

    window.addEventListener('demoEvent', function (e) {
        console.log('4. You click window')
    }, false);
</script>

参考

这篇博客是参考了很多博客和API文档,总结出来的。
包括但不限于:
事件模型浅析
Event
CustomEvent
创建和触发 events

上一篇 下一篇

猜你喜欢

热点阅读