首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

如何理解js的DOM事件系统

  • 25-04-20 18:41
  • 2668
  • 8985
juejin.cn

js事件的继承关系

image.png

浏览器只是区分了不同事件的接口,不同接口有不同的属性而已。即根据不同接口创建出的对象,具有不同的事件属性。

EventTarget

创建一个新的 EventTarget对象实例。即创建一个事件对象,用来监听和派发事件,作用等同于DOM, document, window派发和监听事件。

用法之一可以看这里 原生js如何实现全局事件总线

DOM.dispatchEvent

指定的事件目标派发一个 Event,并以合适的顺序(同步地)调用所有受影响的 EventListener。即利用程序去触发指定DOM的对应事件。

js
代码解读
复制代码
"div">dispatchEvent触发click事件
<script> const div = document.getElementById("div") div.addEventListener("click", () => { console.log("click") }) // 类似于手动点击 div.dispatchEvent(new Event("click")) script>
  • 相关对象

使用dispatchEvent需要具有两个对象,一个是要有派发对象(DOM, document, window等等),另一个是派发的事件对象(即通过Event及其子类创建的对象)。

需要注意的是,我们在通过dispatchEvent派发事件时,该对象的事件监听器需要提前注册好,因为是同步派发。而不像浏览器提供的一些异步任务api。

js
代码解读
复制代码
  • 返回值

派发的事件是否有取消(new Event("click", {cancelable: true})),并且是监听器(多个之一)处理逻辑是否调用了event.preventDefault()。如果二者之一不满足,那么将返回true,否则返回false

js
代码解读
复制代码
div.addEventListener("click", (event) => { console.log("click" ,event, event.target) // event.preventDefault() }) const res = div.dispatchEvent(new Event("click", {cancelable: true})) // true
js
代码解读
复制代码
div.addEventListener("click", (event) => { console.log("click" ,event, event.target) // event.preventDefault() }) div.addEventListener("click", (event) => { console.log("click2" ,event, event.target) event.preventDefault() }) div.dispatchEvent(new Event("click", {cancelable: true})) // false

Event

它是所有事件的主接口。并且也通过了构造函数,可以让我们创建任意名称的事件。并且可以在创建事件对象时可以传入一些事件配置。自定义的事件默认都不能冒泡。

  • "bubbles",默认值为 false,表示该事件是否冒泡。
  • "cancelable",默认值为 false,表示该事件能否被取消。
  • "composed",可选,默认值为 false,指示事件是否会在影子 DOM 根节点之外触发侦听器。是否可以冒泡到自定义元素之外。
js
代码解读
复制代码
const div = document.getElementById("div") document.body.addEventListener("click", (event) => { console.log("body click", event, event.target) // 不会触发,由于自定义事件bubbles: false }) div.addEventListener("click", (event) => { console.log("click" ,event, event.target) event.preventDefault() }) div.addEventListener("click", (event) => { console.log("click2" ,event, event.target) }) div.dispatchEvent(new Event("click", {cancelable: false, bubbles: false}))

Event事件对象属性

不同的事件类型事件对象具有不同的属性,所有事件都继承自Event,所以都具有以下属性。我们来一一介绍一下

image.png

  • isTrusted 表示事件是否由用户行为触发,例如代码触发(dom.click, dom.dispatch...)都返回false。
  • bubbles 表明事件是否会沿 DOM 树向上冒泡。创建事件的时候可以指定事件是否可以冒泡new Event("click", {bubbles: false})。注意这个只是规定事件不能进行冒泡,但是如果事件监听器设置在捕获阶段进行触发,事件依旧会被触发。
js
代码解读
复制代码
document.body.addEventListener("click", (event) => { console.log("body click", event, event.target, event.currentTarget) // event.currentTarget只能在事件处理器中使用,在控制台直接看event是null }, true) div.addEventListener("click", (event) => { console.log("click" ,event, event.target) }, true) div.addEventListener("click", (event) => { console.log("click2" ,event, event.target) }, true) const event = new Event("click", {cancelable: false, bubbles: false}) // 设置不能进行冒泡 div.dispatchEvent(event) // 触发事件

image.png

js
代码解读
复制代码
// 单纯设置事件不能冒泡 document.body.addEventListener("click", (event) => { console.log("body click", event, event.target, event.currentTarget) // event.currentTarget只能在事件处理器中使用,在控制台直接看event是null }, false) div.addEventListener("click", (event) => { console.log("click" ,event, event.target) }, false) div.addEventListener("click", (event) => { console.log("click2" ,event, event.target) }, false) const event = new Event("click", {cancelable: false, bubbles: false}) // 设置不能进行冒泡 div.dispatchEvent(event) // 触发事件

image.png

  • cancelBubble = true 可以阻止事件的继续传播(冒泡或者捕获),可以使用stopPropagation()代替。
  • cancelable 事件是否可以被取消。即通过preventDefault()取消。创建事件的时候可以指定事件是否可以被取消new Event("click", {cancelable: false})
  • composed 指示该事件是否可以从 Shadow DOM 传递到一般的 DOM。
  • currentTarget 标识事件处理器所附加的元素。即绑定事件监听器的对象(一般在事件委托的时候有用)。currentTarget 的值仅在事件处理器中可用。在事件处理器外部,它将为 null。
  • defaultPrevented 当前事件是否调用了 event.preventDefault()方法。如果事件是可以取消的(new Event("click", {cancelable: true})),并且在任意的事件监听器中调用了preventDefault(),该值都会变成true,否则为false。
  • eventPhase 表示事件流当前处于哪一个阶段。
  • returnValue 表示该事件的默认操作是否已被阻止。默认情况下,它被设置为 true,即允许进行默认操作。将该属性设置为 false 即可阻止默认操作。 可以使用preventDefault()代替。
  • srcElement 他是target的别名。
  • target 事件分派到的对象的引用。
  • timeStamp 返回事件创建的时间(以毫秒为单位)。
  • type 表示该事件对象的事件类型。即定义的事件名称。
  • composedPath() 返回事件触发的流程节点对象。如果自定义元素是闭合的那么该流程将包含自定义元素内部元素。如果事件在创建时指定composed: false,那么事件流程将不会包含自定义元素外部dom对象。 image.png
  • ~~initEvent() ~~用来初始化由Document.createEvent() 创建的 event 实例。
  • preventDefault() 阻止事件的默认行为。 如果事件不能取消,他是没有效果的。虽然阻止默认行为,但是冒泡和捕获是不会阻止的。
  • stopPropagation() 阻止捕获和冒泡阶段中当前事件的进一步传播。
  • stopImmediatePropagation() 阻止监听同一事件的其他事件监听器被调用。即在同一个事件触发对象中阻止事件监听器被调用。并且也可以阻止冒泡或者捕获到其他事件触发对象中。

日常开发中的使用

例如抖音搜索,输入文本后,我们必须按下回车Enter键才会进行搜索。所以我们就需要通过KeyboardEvent来创建一个事件帮助我们进行搜索。

js
代码解读
复制代码
const input = document.querySelector(".semi-input.semi-input-default") // 定义一个鼠标按下enter事件 const keyEvent = new KeyboardEvent("keydown", { bubbles: true, cancelable: false, ctrlKey: false, metaKey: false, altKey: false, which: 13, keyCode: 13, key: "Enter", code: "Enter", }); input.dispatchEvent(keyEvent)

事件.gif

往期年度总结

  • 四年沿海城市,刚毕业,一年3家公司
  • 七月仿佛又回到了那一年(2023年中总结)
  • 一位初入职场前端仔的年度终结 <回顾2022,展望2023>
  • 大学两年半的前端学习

往期文章

  • 半年没看vue官网,3.5刚刚发布,趁机整理下
  • 啊,你还在找一款强大的表格组件吗?
  • 前端大量数据层级展示及搜索定位预览
  • 如何从0开始认识m3u8(提取,解析及下载)
  • 展示大量数据节点(tree),引发的一次性能排查
  • ts装饰器的那点东西
  • 这是你所知道的ts类型断言和类型守卫吗?
  • TypeScript官网内容解读
  • 经常使用ts的你,知道这些内容?
  • 你有了解过原生css的scope?
  • 现在比较常用的移动端调试你知道哪些?
  • 众多跨标签页通信方式,你知道哪些?(二)
  • 众多跨标签页通信方式,你知道哪些?
  • 反调试吗?如何监听devtools的打开与关闭
  • 因为原生,选择一家公司(前端如何防笔试作弊)
  • 结合开发,带你熟悉package.json与tsconfig.json配置
  • 如何优雅的在项目中使用echarts
  • 如何优雅的做项目国际化
  • 近三个月的排错,原来的憧憬消失喽
  • 带你从0开始了解vue3核心(运行时)
  • 带你从0开始了解vue3核心(computed, watch)
  • 带你从0开始了解vue3核心(响应式)
  • 3w+字的后台管理通用功能解决方案送给你
  • 入职之前,狂补技术,4w字的前端技术解决方案送给你(vue3 + vite )

专栏文章

  • 重学vue及其生态
  • 前端面试
  • 前端工程化
  • amis 低代码实战
  • 协议与安全
  • 重学react
  • 重学nodejs
  • 工作总结

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,    支持一下博主~

公众号:全栈追逐者,不定期的更新内容,关注不错过哦!

注:本文转载自juejin.cn的Spirited_Away的文章"https://juejin.cn/post/7418394742532243456"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top