携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
说到DOM事件流,我们必须先按以下顺序娓娓道来。
- DOM事件的级别
- DOM事件模型:事件冒泡,事件捕获
- DOM事件流
- DOM事件捕获的具体流程
- event对象的常见应用
- 自定义事件
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多个事件,怎么优化?
- 事件委托代理:把所有子元素的事件给父元素注册,只需绑定一次事件
-
stopPropgagation和stopImmediatePropagation区别- 共同点:都能阻止冒泡
- 不同点:
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阻止后续方法执行
自定义事件
场景:对事件的操作进行自定义
用Event或CustomEvent,区别:
- 用法完全一样
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…