通过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'))
相关推荐
我是苏苏1 小时前
Web开发:C#通过ProcessStartInfo动态调用执行Python脚本
java·服务器·前端
无羡仙2 小时前
Vue插槽
前端·vue.js
哈__2 小时前
React Native 鸿蒙跨平台开发:PixelRatio 像素适配
javascript·react native·react.js
用户6387994773052 小时前
每组件(Per-Component)与集中式(Centralized)i18n
前端·javascript
SsunmdayKT2 小时前
React + Ts eslint配置
前端
开始学java2 小时前
useEffect 空依赖 + 定时器 = 闭包陷阱?count 永远停在 1 的坑我踩透了
前端
zerosrat2 小时前
从零实现 React Native(2): 跨平台支持
前端·react native
狗哥哥2 小时前
🔥 Vue 3 项目深度优化之旅:从 787KB 到极致性能
前端·vue.js
青莲8433 小时前
RecyclerView 完全指南
android·前端·面试
青莲8433 小时前
Android WebView 混合开发完整指南
android·前端·面试