通过dispatchEvent实现代码的方式触发事件

背景介绍

在上一篇文章基于quill封装的富文本编辑器自定义工具栏全屏 - 掘金 (juejin.cn) 中有涉及到全屏的情况下,点击提交需要发送提交的请求且要关闭全屏,这时候就需要涉及到关闭全屏的代码逻辑。再拷贝一份同样的代码逻辑就太冗杂了。而使用dispatchEvent就可以完美的解决这个问题。下面就具体地来介绍下方法及使用案例

实现思路

  • 首先用Event 构造函数创建一个新的 Event 对象。
  • 然后,使用 dispatchEvent() 方法触发事件。

Event 构造函数

使用Event 构造函数来创建一个新事件:

js 复制代码
let event = new Event(type, [,options]);

Event 构造函数接受两个参数:(具体请看Event() - Web API 接口参考 | MDN (mozilla.org))

type

指定事件类型,比如click。或者表示所创建事件的名称

options

为对象类型,有两个属性:

  • bubbles:可选,布尔值类型,表示事件是否冒泡。如果为true,则事件冒泡,默认值为false
  • cancelable:可选,布尔值类型,表示事件是否可以取消,如果为true,则可以取消,默认值为false
  • composed,可选,布尔值类型,指示事件是否会在影子 DOM 根节点之外触发侦听器。默认值为 false,

下面我使用默认的options创建了一个点击事件

js 复制代码
let clickEvent = new Event('click');

UIEvent

UIEvent 是从 Event 派生出来的。包括MouseEvent, TouchEvent, FocusEvent, KeyboardEvent, WheelEvent, InputEvent, 和CompositionEvent。处理Event的一些属性,还提供了提供了更多特定于事件的信息。最好是最好使用 MouseEvent 这样的详细事件构造函数而不是通用的 Event 构造函数。

比如,MouseEvent 事件有许多其他属性,例如 clientX 和 clientY,它们指定事件发生时相对于视口的水平和垂直坐标:

js 复制代码
let clickEvent = new MouseEvent("click", {
  bubbles: true,
  cancelable: true,
  clientX: 150,
  clientY: 150
});

dispatchEvent

创建完事件后,我们就可以使用dispatchEvent() 方法在目标元素上触发它,像这样

csharp 复制代码
element.dispatchEvent(event);

下面就来测试一下:

html 复制代码
<button class="btn">测试dispatchEvent()方法</button>

<script>
  let btn = document.querySelector('.btn');

  btn.addEventListener('click', function () {
    alert('点击了');
  });

  let clickEvent = new Event('click');
  btn.dispatchEvent(clickEvent);
</script>

区分用户触发还是代码触发

通过event.isTrusted 来判断,如果事件来自用户操作则为true,如果事件由代码触发则为false

举个🌰

html 复制代码
<button class="btn1">按钮1</button>
<button class="btn2">按钮2</button>

<script>
  let btn1 = document.querySelector('.btn1')
  let btn2 = document.querySelector('.btn2')
  btn1.addEventListener('click', function (e) {
    console.log('我是按钮1')
    console.log(e.isTrusted)
  })
  btn2.addEventListener('click', function () {
    const event = new MouseEvent('click')
    // 调用了btn1绑定的click事件
    btn1.dispatchEvent(event)
    // console.log(event.isTrusted)
  })
</script>

在自定义全屏的实践使用

需求:实现在全屏状态下,点击确认提交按钮,退出全屏状态

实现:

.app-main为根节点class

js 复制代码
onConfirm () {
  // 拿到根节点
  const app = document.querySelector('.app-main')
  // 拿到自定义工具栏的设置全屏的节点
  const fullBtn = app.querySelector('.ql-fullScreen')
  // 全屏状态就退出全屏,全屏状态才有class(.show-full-screen)
  if (app && app.classList.contains('show-full-screen')) {
    // 调用自定义工具的click事件
    fullBtn && fullBtn.dispatchEvent(new MouseEvent('click'))
  }
}

总结

dispatchEvent可对某个节点的事件达到复用的作用,具体的用法:

js 复制代码
// 拿到class为btn的节点dom
const btn = document.querySelector('.btn')
btn.dispatchEvent(new MouseEvent('click'))
相关推荐
GreenTea5 小时前
GrokBot 核心成员 Lauren Tan:每月交付 2000 个 PR 的人,是怎么用 AI 的
前端·后端·架构
mCell6 小时前
用 Knip 清理 AI Coding 留下的冗余代码
前端·ai编程·前端工程化
dy17177 小时前
vue2树节点刷新后定位到上一节点展开
vue.js
笃行3507 小时前
使用Rokid AIUI做了一个童年推箱子游戏
前端
excel8 小时前
前端加密的作用与使用场景
前端
计算机魔术师9 小时前
纽约时报版权诉讼披露:微软高管内部称训练 AI 是人类历史上最大规模劳动窃取
前端
去伪存真10 小时前
大模型的参数量为什么那么大?
前端·人工智能
IT_陈寒10 小时前
Java空指针这次真把我坑惨了
前端·人工智能·后端
高级程序源11 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
八荒启·交互动画11 小时前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启