详解前端事件流

134 阅读3分钟

事件


作者:©endless

1、事件流

通过一个例子来解释事件流 例如下面的 HTML 文档

<!DOCTYPE html>
<html lang="en">
<html>
    <head>
        <title>event flow</title>
    </head>
    <body>
        <div class="box">
            <div class="fix">Click Me!</div>
        </div>
    </body>
</html>

当点击div.fix时,其事件流触发顺序如下图所示:

事件流.excalidraw.png

Dom的事件流分为 3 个阶段: 事件捕获、到达目标和事件冒泡, 所以当我们点击div.fix的时候,实际上点击事件会从 1-9 走一遍,通常点击事件在冒泡阶段才会被触发。

2、事件处理程序

为响应事件而调用的函数成为事件处理程序, 绑定事件处理程序的方法有一下几种:

HTML事件处理程序

  1. 通过HTML属性绑定精确的动作指令
<div class="fix" onclick="console.log('Clicked!')">Click Me!</div>
  1. 通过HTML属性绑定脚本
<div class="fix" onclick="handler()">Click Me!</div>
<script>
    function handler() {
        console.log('Clicked!');
    }
</script>

Dom事件处理程序 3. 赋值事件处理程序属性

let btn = document.querySelector("div.fix");
btn.onclick = function() {
    console.log("Clicked!");
}
// 移除事件处理程序
btn.onclick = null;
  1. addEventListenerremoveEventListener
let btn = document.querySelector("div.fix");
// 具名函数
function handler() {
    console.log('Clicked!');
}
btn.addEventListener("click", handler, false)
// 匿名函数
btn.addEventListener("click", () => {
    console.log('Clicked!')
}, false);
// 移除事件处理程序
btn.removeEbentLisrener("click", handler, false);
// 这里要注意,使用匿名函数的情况下,无法移除事件监听

3、事件对象

Dom事件处理程序方式指定的函数,会传入一个event对象参数 event对象的属性可以通过查询 mdn 文档获得

这里我们以事件流中的例子为例: 为div.boxdiv.fix绑定两个事件处理程序并写入样式

.box {
    width: 200px;
    height: 200px;
    background-color: #C5C5C5;
}
.fix {
    width: 100px;
    height: 100px;
    background-color: #D6E7F4;
}
const div = document.querySelector("div.box");
const fix = document.querySelector("div.fix");
div.addEventListener("click", (e) => {
    console.log(e.type);
    console.log(e.eventPhase);
    console.log('box');
}, false);
fix.addEventListener("click", (e) => {
    console.log(e.type);
    console.log(e.eventPhase);
    console.log('fix');
}, false);

结果如下:

html.png

点击div.fix, 输出为

click
2
fix
click
3
box

在这个例子中, 点击div.fix, 按照下图顺序,从 1-9 依次执行

事件流.excalidraw.png e.type 输出事件的类型 e.eventPhase 输出事件发生在哪个阶段

也可以将addEventListener()第三个参数改为true, 让事件在捕获阶段被触发

const div = document.querySelector("div.box");
const fix = document.querySelector("div.fix");
div.addEventListener("click", (e) => {
    console.log(e.type);
    console.log(e.eventPhase);
    console.log('box');
}, true);
fix.addEventListener("click", (e) => {
    console.log(e.type);
    console.log(e.eventPhase);
    console.log('fix');
}, false);

输出为:

click
1
box
click
2
fix

可以看出box跑到了前面,我们也可以通过preventDefault()阻止事件冒泡的发生

4、事件类型

这里陈列一些常见的事件

事件事件类型说明
load用户界面事件window上当页面加载完成后触发
resize用户界面时间window或窗格上当窗口或窗格被缩放时触发
scroll用户界面时间当用户滚动包含滚动条的元素时在元素上触发
blur焦点事件当元素失去焦点时触发。这个事件不冒泡,所有浏览器都支持
Focus焦点事件当元素获得焦点时触发。这个事件不冒泡,所有浏览器都支持
click鼠标和滚轮事件单击鼠标主键或按键盘回车键时触发
mousemove鼠标和滚轮事件鼠标光标在元素上移动时反复触发
keydown键盘与输入事件按下键盘上某个键时触发,而且持续按住会重复触发
keyup键盘与输入事件释放键盘上某个键时触发

最后,多看,多练习,加油!