前言
在当今数字时代,前端技术正日益成为塑造用户体验的关键。而其中一个不可或缺的核心概念就是JavaScript的事件模型。或许你是刚踏入前端领域的小白,或者是希望深入了解事件模型的开发者,不论你的经验如何,本篇博客都将带你揭开事件模型的神秘面纱。
🚀 作者简介:程序员小豪,全栈工程师,热爱编程,曾就职于蔚来,现就职于某互联网大厂,技术栈:Vue、React、Python、Java
🎈 本文收录于小豪的前端系列专栏,后续还会更新前端入门以及前端面试的一些相关文章,手把手带你从零学习前端到面试找工作,并如果有想进入前端领域工作的同学,这个前端专栏会对你有所帮助,欢迎关注起来呀
🌼 本人也会持续的去关注AIGC以及人工智能领域的一些动向并总结到博客中,大家感兴趣的可以关注一下我的人工智能专栏
🌊 云原生的入门学习系列,大家有兴趣的可以看一看
1.事件与事件流
javascript
中的事件,可以理解就是在HTML
文档或者浏览器中发生的一种交互操作,使得网页具备互动性, 常见的有加载事件、鼠标事件、自定义事件等
由于DOM
是一个树结构,如果在父子节点绑定事件时候,当触发子节点的时候,就存在一个顺序问题,这就涉及到了事件流的概念
事件流都会经历三个阶段:
- 事件捕获阶段(capture phase)
- 处于目标阶段(target phase)
- 事件冒泡阶段(bubbling phase)
事件冒泡是一种从下往上的传播方式,由最具体的元素(触发节点)然后逐渐向上传播到最不具体的那个节点,也就是DOM中最高层的父节点
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件冒泡</title> </head> <body> <button id="clickMe">按钮</button> </body> </html>
然后,我们给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'); };
最后得到的输出如下:
点击事件首先在button元素上发生,然后逐级向上传播
事件捕获与事件冒泡相反,事件最开始由不太具体的节点最早接受事件, 而最具体的节点(触发节点)最后接受事件
2. 事件模型
事件模型可以分为三种:
- 原始事件模型(DOM0级)
- 标准事件模型(DOM2级)
- IE事件模型(基本不用)
原始事件模型
原始事件模型(DOM0级事件模型)是事件绑定的最简单方式,适用于那些想要快速添加事件监听的场景。这种模型有两种绑定方式:直接在HTML代码中绑定和通过JS代码绑定。让我们来看看它们的特点和应用。
HTML中直接绑定事件
<input type="button" onclick="fun()">
通过JS代码绑定事件
var btn = document.getElementById('btn'); btn.onclick = fun;
原始事件模型的特点:
- 绑定速度快: 原始事件模型绑定速度非常快,但也可能因为绑定过于迅速,导致事件无法在页面完全加载时执行。
- 仅支持冒泡: 原始事件模型只支持事件冒泡,不支持捕获。
- 同类型事件只能绑定一次: 如果尝试为同一个元素绑定多个同类型事件,后绑定的事件会覆盖之前的事件。
<input type="button" id="btn" onclick="fun1()"> var btn = document.getElementById('btn'); btn.onclick = fun2;
对于上面的情况,尝试为同一个按钮绑定两个点击事件时,后绑定的事件会覆盖之前的事件。
要删除DOM0级事件处理程序,只需将对应的事件属性置为null
即可。
btn.onclick = null;
标准事件模型
标准事件模型(DOM2级事件模型)是更加强大和灵活的事件处理方式。在标准事件模型中,一个事件共有三个阶段:捕获阶段、处理阶段和冒泡阶段。让我们深入了解标准事件模型的特点和使用方法。
事件捕获阶段、处理阶段和冒泡阶段
- 事件捕获阶段: 事件从
document
向下传播到目标元素,检查经过的节点是否绑定了事件监听函数,如果有则执行。 - 事件处理阶段: 事件到达目标元素,触发目标元素的监听函数。
- 事件冒泡阶段: 事件从目标元素冒泡回
document
,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。
在标准事件模型中,事件绑定和移除监听函数的方式如下:
addEventListener(eventType, handler, useCapture); removeEventListener(eventType, handler, useCapture);
标准事件模型的特点:
- 支持多个事件处理器: 在一个DOM元素上可以绑定多个事件处理器,它们不会相互冲突。
btn.addEventListener('click', showMessage1, false); btn.addEventListener('click', showMessage2, false); btn.addEventListener('click', showMessage3, false);
- 执行时机:
useCapture
参数设置为true
时,在捕获阶段执行监听函数;设置为false
时,在冒泡阶段执行监听函数。
通过以下例子,我们可以更好地理解事件处理阶段的执行时机:
<div id='div'> <p id='p'> <span id='span'>点击我!</span> </p > </div>
设置点击事件:
var div = document.getElementById('div'); var p = document.getElementById('p'); function onClickFn (event) { var tagName = event.currentTarget.tagName; var phase = event.eventPhase; console.log(tagName, phase); } div.addEventListener('click', onClickFn, false); p.addEventListener('click', onClickFn, false);
点击"点击我!"后,输出如下:
P 3 DIV 3
我们可以看到,p
和div
都在冒泡阶段响应了事件,由于冒泡的特性,内部的p
先于外层的div
作出了响应。
如果我们将useCapture
参数改为true
:
div.addEventListener('click', onClickFn, true); p.addEventListener('click', onClickFn, true);
输出如下:
DIV 1 P 1
两者在捕获阶段响应事件,因此div
会先于p
作出响应。
IE事件模型
IE事件模型共有两个过程:
- 事件处理阶段:事件到达目标元素, 触发目标元素的监听函数。
- 事件冒泡阶段:事件从目标元素冒泡到
document
, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行
事件绑定监听函数的方式如下:
attachEvent(eventType, handler)
事件移除监听函数的方式如下:
detachEvent(eventType, handler)
举个例子:
var btn = document.getElementById('.btn'); btn.attachEvent(‘onclick’, showMessage); btn.detachEvent(‘onclick’, showMessage);
总结
在本篇博客中,我们一起探索了JavaScript事件模型的四大概念:事件与事件流、原始事件模型、标准事件模型、IE事件模型。JavaScript是一门非常强大且广泛应用的编程语言。掌握了这些基本的语法和概念,你已经具备了入门JavaScript编程的基础。未来,你将能够创建更加交互性的网页,实现更多惊艳的动态效果,甚至搭建出属于自己的Web应用。但这只是一个开始,还有许多更深入的主题等待你去探索。