JavaScript中的事件模型
事件与事件流
javascript
中的事件,可以理解就是在HTML
文档或者浏览器中发生的一种交互操作,使得网页具备互动性, 常见的有加载事件、鼠标事件、自定义事件等
由于DOM
是一个树结构,如果在父子节点绑定事件时候,当触发子节点的时候,就存在一个顺序问题,这就涉及到了事件流的概念
事件流都会经历三个阶段:
-
事件捕获阶段(capture phase)
-
处于目标阶段(target phase)
-
事件冒泡阶段(bubbling phase)
事件冒泡是一种从下往上的传播方式,由最具体的元素(触发节点)然后逐渐向上传播到最不具体的那个节点,也就是DOM
中最高层的父节点
然后,我们给button
和它的父元素,加入点击事件
var button = document.getElementById('clickMe');
button.onclick = function() {
console.log('1.Button');
};
document.body.onclick = function() {
console.log('2.body');
};
document.onclick = function() {
console.log('3.document');
};
window.onclick = function() {
console.log('4.window');
};
点击按钮,输出如下
1.button
2.body
3.document
4.window
1234
点击事件首先在button
元素上发生,然后逐级向上传播
事件捕获与事件冒泡相反,事件最开始由不太具体的节点最早接受事件, 而最具体的节点(触发节点)最后接受事件
事件模型
事件模型可以分为三种:
-
原始事件模型(DOM0级)
-
标准事件模型(DOM2级)
-
IE事件模型(基本不用)
原始事件模型
HTML绑定
<button onClick='handleFunction'/>
JS绑定
const el = document.getElementById('test-button')
el.onClick = callback
特点
-
绑定速度快
DOM0
级事件具有很好的跨浏览器优势,会以最快的速度绑定,但由于绑定速度太快,可能页面还未完全加载出来,以至于事件可能无法正常运行
-
只支持冒泡,不支持捕获
-
同一个类型的事件只能绑定一次
<input type="button" id="btn" onclick="fun1()">
var btn = document.getElementById('.btn');
btn.onclick = fun2;
如上,当希望为同一个元素绑定多个同类型事件的时候(上面的这个btn
元素绑定2个点击事件),是不被允许的,后绑定的事件会覆盖之前的事件
删除 DOM0
级事件处理程序只要将对应事件属性置为null
即可
btn.onclick = null;
标准事件模型
标准事件类型分为三个阶段:
事件捕获阶段:
事件从document处开始,依次向下进行传递,当向下传递时,遇到的元素如果也有绑带该类事件,就会触发。
事件处理阶段:
事件到达目标元素,**执行事件绑定的函数**
事件冒泡阶段:
冒泡到document处,**遇到的元素如果也有绑带该类事件,就会触发。**
标准事件模型绑定事件:
-
eventType
指定事件类型(不要加on) -
handler
是事件处理函数 -
useCapture
是一个boolean
用于指定是否在捕获阶段进行处理,一般设置为false
与IE浏览器保持一致
addEventListener(eventType,handler,useCap)
//删除事件
removeEventListener(eventType,handler,useCapture)
🌰例子:
const el = document.getElementById('.btn')
el.addEventListener('click',showMessage,false)
el.removeEventListener('click',showMessage,false)
特性
-
可以在一个
DOM
元素上绑定多个事件处理器,各自并不会冲突
btn.addEventListener(‘click’, showMessage1, false);
btn.addEventListener(‘click’, showMessage2, false);
btn.addEventListener(‘click’, showMessage3, false);
-
执行时机
当第三个参数(useCapture
)设置为true
就在捕获过程中执行,反之在冒泡过程中执行处理函数
🌰例子:
<div id='div'>
<p id='p'>
<span id='span'>Click Me!</span>
</p >
</div>
<script>
const eDiv = document.getElementById('div')
const eSpan = document.getElementById('span')
function handleClick(event){
const tagName = event.currentTarget.tagName
const phase = event.eventPhase
console.log(tagName,phase)
}
eSpan.addEventLinstener('click',handleClick,false)
eDiv.addEventLinstener('click',handleClick,false)
//上述使用了eventPhase,返回一个代表当前执行阶段的整数值。1为捕获阶段、2为事件对象触发阶段、3为冒泡阶段
</script>
输出:
P 3
DIV 3
如果把false设置为true
div.addEventListener('click', onClickFn, true);
p.addEventListener('click', onClickFn, true);
输出:
DIV 1
P 1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?