【每日一题NO.54】说下你对时间流的理解
人生苦短,总需要一点仪式感。比如学前端~
目录:
事件
事件流
事件冒泡、事件捕获
DOM 事件处理
DOM0
DOM2
事件
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("小石头");
}
script>
但是会存在问题:
<div id="btn">点击div>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
console.log("小石头");
}
btn.onclick = function(){
console.log("石头姐");
}
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.onclick = function(){
console.log(1)
}
btn2.onclick = function(){
console.log(2)
}
btn3.onclick = function(){
console.log(3)
}
script>
当点击 div#btn1 的时候,会依次输入 1,2,3,这就是事件冒泡,DOM0 级只支持冒泡阶段
DOM2
DOM2定义了两个方法:
addEventListener 添加事件侦听器 removeEventListener 删除事件侦听器
这两个方法均有三个参数:
第一个参数是要处理的事件名称 第二个参数是作为事件处理程序的函数名称 第三个参数是一个布尔值,默认为false。false表示使用冒泡机制,true表示使用捕获机制
<div id="btn">点击div>
<script>
var btn = document.getElementById("btn");
btn.addEventListener("click", helloFun, false);
btn.addEventListener("click", helloAgainFun, false);
function helloFun(){
console.log("hello");
}
function helloAgainFun(){
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冒泡
阻止冒泡 event.stopPropagation()
btn2.addEventListener(
"click",
function (ev) {
ev.stopPropagation();
console.log("btn2捕获");
},
true
);
所有《每日一题》的 知识大纲索引脑图 整理在此:https://www.yuque.com/dfe_evernote/interview/everyday
你也可以点击文末的 “阅读原文” 快速跳转
评论