持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
核心描述
- 浏览器的事件模型,主要基于 DOM Events 规范(DOM0 Events、DOM2 Events、DOM3 Events)
- 浏览器的事件模型,主要是 DOM2 Events 规范中规定的事件流模型,分为3个阶段:
- 事件捕获,最先发生,触发顺序
document -> <html> -> <body> -> target element
- 到达目标,实际的目标元素
target element
接收到事件 - 事件冒泡,到达目标元素后,触发顺序
target element -> body -> html -> document
- 事件捕获,最先发生,触发顺序
- 所以可以理解为事件模型即浏览器对规范中上述的3个阶段的实现
- 主流的浏览器基本都实现了事件捕获和事件冒泡,我们实际项目中用的更多的其实也是事件冒泡,如果要在事件捕获阶段触发事件响应逻辑,需要在
targetElement.addEventListener('click',handler,true )
第三个参数中设置为 true,则表示在捕获阶段调用事件处理程序
知识拓展
- 在 HTML 代码中触发事件的方式有三种:
- 在元素中直接调用
// btnOnClickHandle 方法为当前文档中可以直接访问的方法,需要注意其作用域 <div id='myBtn' onclick="btnOnClickHandle">点击按钮</div>
- 通过
onXXX
的方式调用
const btnEle = document.getElementById('myBtn') myBtn.onclick = btnOnClickHandle () { // 处理按钮点击事件的相关逻辑 }
- 通过
addEventListener
的方式调用(推荐)
const btnEle = document.getElementById('myBtn') myBtn.addEventListener('click', btnOnClickHandle, false) function btnOnClickHandle () { // 处理按钮点击事件的相关逻辑 }
- 需要注意一些比较老的浏览器版本,对事件的处理方式有差异,以及兼容性的问题,所以在项目中需要做一些兼容处理,或是直接调用第三方库
- 比如 IE8 或者更早版本的浏览器,并不支持
addEventListener
的调用,而是其特有的attachEvent
- 不过随着最新微软的公告,今后将不再继续支持 IE,而是推荐用户使用基于 Chrome 内核的 Edge 浏览器。所以作为开发者而言,我们应该将更多的精力放在实际业务中,而非无休止的兼容代码上,但这并不意味着我们应该放弃对这方面的思考和警惕,因为用户软件的更迭,总是有时间成本的,作为开发者我们还是应该了解到相关的技术原因,以便于更好的服务用户。
- 比如 IE8 或者更早版本的浏览器,并不支持
- 除了理解事件模型,我们也应该关注不断更新的事件规范以及浏览器支持的事件类型,比如:
- 用户界面事件(UIEvent):涉及与 BOM 交互的通用浏览器事件
- 焦点事件(FocusEvent):在元素获得和失去焦点时触发
- 鼠标事件(MouseEvent):使用鼠标在页面上执行某些操作时触发
- 滚轮事件(WheelEvent):使用鼠标滚轮(或类似设备)时触发
- 输入事件(InputEvent):向文档中输入文本时触发
- 键盘事件(KeyboardEvent):使用键盘在页面上执行某些操作时触发
- 合成事件(CompositionEvent):在使用某种 IME(Input Method Editor,输入法编辑器)输入字符时触发
- ……
- 需要注意,在 DOM2 Event 中的变化事件(Mutation Events)已经被废弃,并用 MutationObserver API取代,用于在 DOM 被修改时异步执行回调,可以观察整个文档、DOM 树的一部分,或某个元素。此外还能观察元素属性、子节点、文本,或者前三者任意组合的变化。
- 事件性能优化,在 JavaScript 中,页面中事件处理程序的数量和页面整体性能直接相关。
- 原因分析:
- 每个函数都是对象,都占用内存空间,对象越多,性能越差
- 为指定事件处理程序所需访问 DOM 的次数会先期造成整个页面交互的延迟
- 解决方案:
- 事件委托,利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件,通过回调方法的 target 对象的属性,来判断最终生效的元素,再做对应的处理,可以减少事件的绑定数量
- 删除事件处理程序:在业务的合适时机,如模块隐藏或已完成逻辑处理,则对后续不再使用的事件监听进行移除
- 原因分析:
- 事件拓展
- 自定义右键菜单,oncontextmenu 事件,可以屏蔽或自定义右键菜单
- 页面卸载事件,beforeunload 事件,可以在浏览器离开当前页面之前触发,需要注意的事,如果想要弹出对应的弹窗提示,则需要用户有过对应的交互操作才会触发,否则会直接离开页面,而不会弹出弹窗。
参考资料
- 《JavaScript 高级程序设计(第4版)》
- DOM2 Events 规范:www.w3.org/TR/DOM-Leve…
- DOM3 Events 规范:www.w3.org/TR/2009/WD-…
浏览知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。