你知道DOM事件流是怎样的吗

158 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

说到DOM事件流,我们必须先按以下顺序娓娓道来。

  1. DOM事件的级别
  2. DOM事件模型:事件冒泡,事件捕获
  3. DOM事件流
  4. DOM事件捕获的具体流程
  5. event对象的常见应用
  6. 自定义事件

DOM事件级别

(没有DOM1,因为DOM1没有与事件相关特性)

  • DOM0

    • element.onclick = function () {}
  • DOM2

    • element.addEventListener('click', function(){}, false)
    • 第3个参数:false代表冒泡 true代表捕获
  • DOM3

    • 事件定义方式没变,事件类型增加了鼠标事件,键盘事件等
    • element.addEventListener('keyup', function() {}, false)

DOM事件模型

  • 事件冒泡
  • 事件捕获

DOM事件流

事件流:浏览器在为当前页面与用户交互过程中,比如点击鼠标左键,如何传递到页面上

完整事件流分三个阶段:

  • 事件捕获

    • window接收事件=>传给document=>html=>body=>父级元素等=>目标元素
  • 目标阶段(事件通过捕获到达目标元素)

  • 冒泡阶段(从目标元素上传到window对象)

DOM事件捕获的具体流程

js获取html:document.documentElement

js获取body:document.body(兼容问题)

事件捕获包含:window接收事件=>传给document=>html=>body=>父级元素等=>目标元素

冒泡流程就是倒过来

event对象的常见应用

  • 拿鼠标值和键盘值,event.keyCode

  • event.preventDefault()阻止默认行为

  • event.stopPropgagation()阻止事件冒泡(当父子元素绑定事件不同时,子元素单击的时候不需要冒泡到父)

  • event.stopImmediatePropagation()控制事件响应优先级(注册了两个click事件,当第一个click函数被执行时,阻止第二个)

  • event.currentTarget 事件委托时的父元素

  • event.target 事件委托时的执行事件的子元素

  • 循环注册n多个事件,怎么优化?

    • 事件委托代理:把所有子元素的事件给父元素注册,只需绑定一次事件
  • stopPropgagationstopImmediatePropagation区别

    • 共同点:都能阻止冒泡
    • 不同点:stopImmediatePropagation不仅阻止事件冒泡,还会阻止该事件后面的监听方法执行
var div = document.getElementById('div');
// 添加第一个监听事件
div.addEventListener('click', function(){
  console.log('click event 1')
});
// 添加第二个监听事件,stopPropagation阻止冒泡
div.addEventListener('click', function(){
  console.log('click event 2')
});
// 添加第三个监听事件,stopImmediatePropagation阻止冒泡
div.addEventListener('click', function(){
  console.log('click event 3')
});
// 添加第四个监听事件,stopPropagation阻止冒泡
div.addEventListener('click', function(){
  console.log('click event 4')
});

// 点击后执行结果为
click event 1
click event 2
click event 3 //  stopImmediatePropagation阻止后续方法执行

自定义事件

场景:对事件的操作进行自定义

EventCustomEvent,区别:

  • 用法完全一样
  • Event只能指定事件名,CustomEvent除了指定事件名,还可以加参数
// 定义
var eve = new Event('custome')
div.dispatchEvent(eve)

// 使用
div.addEventListener('custome', function() {
    console.log('custome')
})
// 定义
var myEvent = new CustomEvent(
    "anAction",
    {
        detail: { 
          description: "a description of the event",
          timeofevent: new Date(),
          eventcode: 2 
        }, // detail:初始化时传递的数据
        bubbles: true, // 是否会冒泡
        cancelable: true // 事件是否可以被取消
    }
);
document.dispatchEvent(myEvent);

// 使用
document.addEventListener("anAction", customEventHandler);
function customEventHandler() {
  console.log(window.event.detail.description);
}

自定义事件使用场景解耦多模块开协作

关于自定义事件的更详细文章参考:juejin.cn/post/684490…