当前位置: 首页 > news >正文

Web前端入门:JavaScript 由程序触发绑定事件的几种方式

开发中经常会遇这样的需求:点击 A 元素的时候,需要触发 B 元素的事件,比如:点击一个 div 元素,然后触发 input:file 的 click 事件,用来选择文件上传。

click 方法

以上需求可通过元素的 click 方法触发:

<style>.test2 {padding: 4px;margin-top: 12px;}
</style>
<input type="file" class="test1"><br>
<button class="test2">前端路引--事件测试</button><script>(() => {const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')test2.addEventListener('click', () => {//  点击 test2 后,触发 test1 的 click 事件test1.click()})})()
</script>

效果:

77-1

点击事件有 click 方法可以使用,如果需求是点击 A 元素触发 B 元素的 mousedown 事件,那能用 mousedown 方法吗?

<style>button {padding: 4px;margin-top: 12px;}
</style><button class="test1">前端路引--事件测试 test1</button><br>
<button class="test2">前端路引--事件测试 test2</button><script>(() => {const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')test1.addEventListener('mousedown', () => {console.log('test1 mousedown')})test2.addEventListener('click', () => {//  点击 test2 后,触发 test1 的 click 事件test1.click()test1.mousedown();})})()
</script>

效果:

77-2

想法在实现上遇到了问题,html 元素上不存在 mousedown 方法,click 方法也只能触发 click 事件,无法触发绑定的 mousedown 事件,那么有办法可以做到吗?答案肯定是有的~~

dispatchEvent 方法

dispatchEvent 方法可以触发任意事件,其参数是一个实例化的 Event 对象。以上例子中使用 dispatchEvent 方法,实现效果如下:

<style>button {padding: 4px;margin-top: 12px;}
</style><button class="test1">前端路引--事件测试 test1</button><br>
<button class="test2">前端路引--事件测试 test2</button><script>(() => {const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')test1.addEventListener('mousedown', () => {console.log('test1 mousedown')})test2.addEventListener('click', () => {//  点击 test2 后,触发 test1 的 click 事件const event = new Event('mousedown')test1.dispatchEvent(event)})})()
</script>

效果:

77-3

Event 对象

语法:

new Event(type, options)

该对象有两个参数:

第一个事件类型 type 为必传参数,不传则报错 Uncaught TypeError: Failed to construct 'Event': 1 argument required, but only 0 present.

第二个 options 参数为可选参数,拥有三个属性:bubbles: 可选,Boolean 类型,默认值为 false,表示该事件是否冒泡。cancelable: 可选,Boolean 类型,默认值为 false,表示该事件能否被取消。composed: 可选,Boolean 类型,默认值为 false,指示事件是否会在影子 DOM 根节点之外触发侦听器。

bubbles 冒泡:

关于冒泡很好理解,就是子元素是否能冒泡到父元素,如下例子 test1 触发的事件将会冒泡到容器 test-container 上。

<div class="test-container"><button class="test0">前端路引--事件测试 test0</button>
</div>
<button class="test1">前端路引--事件测试 test1</button>
<button class="test2">前端路引--事件测试 test2</button><script>(() => {const test0 = document.querySelector('.test0')const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')document.querySelector('.test-container').addEventListener('mousedown', () => {console.log('test-container mousedown')})test1.addEventListener('click', () => {// 默认不允许冒泡const event = new Event('mousedown')test0.dispatchEvent(event)})test2.addEventListener('click', () => {// 配置 bubbles 允许冒泡const event = new Event('mousedown', { bubbles: true })test0.dispatchEvent(event)})})()
</script>

效果:

77-4

cancelable 事件能否取消:

true:表示事件是可取消的,调用 event.preventDefault() 会阻止浏览器的默认行为。false:表示事件不可取消,调用 event.preventDefault() 无效。

实测就算传入的是传入为 false,也能调用 event.preventDefault() 并不会报错,对 Event 对象无效,但是对 MouseEvent 对象有用(参考后文)。

设置此参数可在事件的 event 参数上获取传入的值:

<input type="file" name="" id="" class="file"><br>
<button class="test1">前端路引--事件测试 cancelable: false</button><br>
<button class="test2">前端路引--事件测试 cancelable: true</button><script>(() => {const file = document.querySelector('.file')const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')file.addEventListener('click', () => {console.log('cancelable', event.cancelable);})test1.addEventListener('click', () => {const event = new Event('click', { cancelable: false })file.dispatchEvent(event)})test2.addEventListener('click', () => {const event = new Event('click', { cancelable: true })file.dispatchEvent(event)})})()
</script>

效果:

77-5

dispatchEvent 触发的 Event 对象,并 不会响应 元素本身的默认事件,比如 a 标签的跳转,input:file 的文件选择等。

composed 是否允许穿透 shadow DOM 节点:

如果不使用影子节点,这属性基本没啥用处,影子节点在常规开发中很少使用~~

一个简单示例:

<div class="wrapper"><my-component id="host"></my-component>
</div>
<script>(() => {class MyComponent extends HTMLElement {constructor() {super();const shadow = this.attachShadow({ mode: 'open' });shadow.innerHTML = `<button id="inner-button1">影子节点内部按钮1--前端路引</button><button id="inner-button2">影子节点内部按钮2--前端路引</button>`;}}customElements.define('my-component', MyComponent);const host = document.querySelector('#host');const innerBtn1 = host.shadowRoot.querySelector('#inner-button1')const innerBtn2 = host.shadowRoot.querySelector('#inner-button2')innerBtn1.addEventListener('click', () => {const event = new Event('custom-event', { bubbles: true,    // 允许在 Shadow DOM 内部冒泡composed: false   // 禁止穿透到外部 DOM});innerBtn1.dispatchEvent(event);});innerBtn2.addEventListener('click', () => {const event = new Event('custom-event', { bubbles: true,    // 允许在 Shadow DOM 内部冒泡composed: true   // 允许穿透到外部 DOM});innerBtn2.dispatchEvent(event);});// 尝试在外部 DOM 监听事件host.addEventListener('custom-event', () => {console.log('外部 DOM 监听到事件'); // 不会触发});})()
</script>

效果:

77-6

CustomEvent 对象

Event 对象没办法传入自定义数据,某些特定需求需要传入自定义参数时,可以祭出 CustomEvent 对象。

CustomEvent 继承 Event,所以 Event 支持的配置都支持,只是多了一个自定义数据字段。

示例:

<button class="test1">前端路引--事件测试 test1</button><br>
<button class="test2">前端路引--事件测试 test2</button><script>(() => {const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')test1.addEventListener('dev', (event) => {console.log('自定义数据:', event.detail);})test2.addEventListener('click', () => {//  点击 test2 后,触发 test1 的 click 事件const event = new CustomEvent('dev', {detail: {name: '前端路引',age: 1}})test1.dispatchEvent(event)})})()
</script>

以上代码使用了 CustomEvent 触发了自定义的 dev 事件,并传入了自定义数据。

效果:

77-7

MouseEvent

前面说了 dispatchEvent 触发的 Event 对象不会响应元素本身的默认事件,但可以通过 MouseEvent 对象来触发一些元素本身的默认事件。

如下例子:

<input type="file" name="" id="" class="file"><br>
<button class="test1">前端路引--事件测试 cancelable: false</button><br>
<button class="test2">前端路引--事件测试 cancelable: true</button><script>(() => {const file = document.querySelector('.file')const test1 = document.querySelector('.test1')const test2 = document.querySelector('.test2')file.addEventListener('click', () => {event.preventDefault()console.log('cancelable', event.cancelable);})test1.addEventListener('click', () => {const event = new MouseEvent('click', { cancelable: false })const res = file.dispatchEvent(event)console.log(`${!res ? '调用了' : '没调用'} preventDefault`);})test2.addEventListener('click', () => {const event = new MouseEvent('click', { cancelable: true })const res = file.dispatchEvent(event)console.log(`${!res ? '调用了' : '没调用'} preventDefault`);})})()
</script>

效果:

77-8

dispatchEvent 返回值当 event 可被取消(cancelable 值为 true),且 event 中至少有一个事件处理程序调用了 Event.preventDefault() 方法时,返回 false。否则,返回 true。

写在最后

按照 MDN 的说法,由程序触发的事件,还有一个专用名词 合成事件,表示不是浏览器本身触发的事件。

除了本文例子中的几个 Event 对象外,还有一些其他对象,在使用时可参考 MDN 文档。

用户交互:鼠标、键盘、触摸交互 MouseEventKeyboardEventTouchEvent

表单与输入:输入框、表单提交 InputEventSubmitEvent

媒体控制:音视频播放、设备流 MediaStreamTrackEvent

拖放与剪贴板:拖拽操作、复制粘贴 DragEventClipboardEvent

存储与通信:本地存储、跨文档通信 StorageEventMessageEvent

错误与调试:脚本错误捕获 ErrorEvent

设备与传感器:方向、加速度检测 DeviceOrientationEvent

动画与过渡:CSS 动画/过渡生命周期 AnimationEventTransitionEvent

文章转载自:前端路引

原文链接:Web前端入门第 77 问:JavaScript 由程序触发绑定事件的几种方式 - 前端路引 - 博客园

体验地址:JNPF快速开发平台

http://www.lryc.cn/news/588775.html

相关文章:

  • redisson 设置了过期时间,会自动续期吗
  • [ctfshow web入门]web98 学习PHP的引用
  • LeetCode 3136.有效单词:遍历模拟
  • 21.映射字典的值
  • 连接new服务器注意事项
  • 非实时的防控场景
  • LLM面试题及讲解 4
  • 【Tauri】Tauri 2.x+Vue自动更新教程对接后端接口更新
  • C++--哈希
  • CPU寄存器、进程上下文与Linux O(1)调度器原理
  • 知识付费小程序资质全解析
  • 进程的内存映像,只读区,可读写区,堆,共享库,栈详解
  • 【机器学习基础【5】】Python数据科学三件套:从数据创建到处理再到可视化实战
  • 链表的 哑结点的本质
  • 排序算法实战(上)
  • 经典排序算法之希尔排序
  • 解锁Python爬虫:数据获取与清洗的进阶指南
  • 深入浅出 RabbitMQ-核心概念介绍与容器化部署
  • Zabbix钉钉告警
  • 如何将华为文件传输到电脑
  • C++ - 仿 RabbitMQ 实现消息队列--muduo快速上手
  • 每日钉钉API探索:chooseUserFromList灵活选取自定义联系人
  • 变更缓冲池简介
  • Git分支管理与工作流详解
  • STL的一些知识点
  • Java-特殊文件、日志技术
  • RTDETR融合CFFormer中的FeatureCorrection_s2c模块
  • 下一代防火墙-web防护
  • Android弹窗
  • 2025牛客暑期多校训练记录