【每日一题NO.87】说说你对DOM事件流的理解
前端印记
共 3141字,需浏览 7分钟
·
2021-11-18 16:21
事件
JavaScript
和 HTML
之间的交互是通过事件实现的。
事件就是通过文档或浏览器窗口发生的一些特定的交互瞬间。
可以使用 监听器 (或者事件处理程序) 来预定事件,以便来执行相应的代码
事件流
描述的是页面中事件传播的顺序。
当事件发生的时候,会在元素节点之间按照特定的顺序传播,这个传播的过程叫做 DOM 的事件流
。
这个传播过程是:事件捕获 -- 事件目标 -- 事件冒泡。
而早期的 IE 和 NetScape 提出了完全相反的事件流概念,IE 是事件冒泡,而 NetScape 的事件流就是事件捕获。
事件冒泡、事件捕获
IE 提出的事件流是 事件冒泡
,即从下到上,从目标触发的元素逐级往下向上传播,直到 window 对象。而 NetScape 的事件流就是 事件捕获
,即从 document 对象逐级向下传播到目标元素。由于 IE 低版本浏览器不支持,所以很少使用事件捕获。后来 ECMAScript 在 DOM2 中对事件流进行了进一步规范,基本上就是上述二者的结合,
DOM2 中事件规定的事件流包括三个阶段:
事件 捕获 阶段:事件从Document节点上 自上而下 向目标节点传播的阶段 处于目标阶段:真正的目标节点正在处理事件的阶段 事件 冒泡 阶段:事件从目标节点 自下而上 向Document传播的阶段
DOM 事件处理
DOM 节点增加了对事件处理,其分为四个级别
DOM0
DOM0 级事件具有极好的跨浏览器优势,会以最大的速度绑定
第一种方式是内联模型【行内模式】
<div onclick="btnClick()">clickdiv>
<script>
function btnClick(){
console.log("hello");
}
script>
缺点是:不符合 W3C 中关于内容与行为分离的基本规范
第二种方式是脚本模式
<div id="btn">点击div>
<script>
var btn=document.getElementById("btn");
btn.onclick=function(){
console.log("sunny");
}
script>
但是会存在问题
<div id="btn">点击div>
<script>
var btn=document.getElementById("btn");
btn.onclick=function(){
console.log("sunny");
}
btn.onclick=function(){
console.log("sunny-sunny");
}
script>
这个时候只能输出 sunny-sunny。很明显的是:
第一个事件函数被第二个事件函数给覆盖掉了,所以脚本模型的缺点就是:同一个节点只能添加一次同类型事件
<div id="btn3">
btn3
<div id="btn2">
btn2
<div id="btn1">
btn1
div>
div>
div>
<script>
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
let btn3 = document.getElementById("btn3");
btn1.onclick=function(){
console.log(1)
}
btn2.onclick=function(){
console.log(2)
}
btn3.onclick=function(){
console.log(3)
}
script>
当点击 btn1 的时候,会依次输入 1,2,3,这就是事件冒泡,DOM0 级只支持冒泡阶段
DOM2
DOM2定义了两个方法:
addEventListener
添加事件侦听器removeEventListener
删除事件侦听器
这两个方法均有三个参数:
第一个参数是要处理的时间名称 第二个参数是作为事件处理程序的函数名称 第三个参数是一个布尔值,默认false表示使用冒泡机制,true表示捕获机制
<div id="btn">点击div>
<script>
var btn=document.getElementById("btn");
btn.addEventListener("click",hello,false);
btn.addEventListener("click",helloagain,false);
function hello(){
console.log("hello");
}
function helloagain(){
console.log("hello again");
}
script>
捕获冒泡的顺序
<div id="btn3">
btn3
<div id="btn2">
btn2
<div id="btn1">
btn1
div>
div>
div>
<script>
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
let btn3 = document.getElementById("btn3");
btn1.addEventListener('click', function () {
console.log('btn1捕获')
}, true)
btn1.addEventListener('click', function () {
console.log('btn1冒泡')
}, false)
btn2.addEventListener('click', function () {
console.log('btn2捕获')
}, true)
btn2.addEventListener('click', function () {
console.log('btn2冒泡')
}, false)
btn3.addEventListener('click', function () {
console.log('btn3捕获')
}, true)
btn3.addEventListener('click', function () {
console.log('btn3冒泡')
}, false)
script>
点击btn1,其结果为:btn3捕获 btn2捕获 btn1捕获 btn1冒泡 btn2冒泡 btn3冒泡
阻止冒泡
btn2.addEventListener(
"click",
function (ev) {
ev.stopPropagation();
console.log("btn2捕获");
},
true
);
所有《每日一题》的 知识大纲索引脑图 整理在此:https://www.yuque.com/dfe_evernote/interview/everyday
你也可以点击文末的 “阅读原文” 快速跳转
评论