Web前端入门第 77 问: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>
效果:
点击事件有 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>
效果:
想法在实现上遇到了问题,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>
效果:
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>
效果:
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>
效果:
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>
效果:
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
事件,并传入了自定义数据。
效果:
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>
效果:
dispatchEvent 返回值当 event 可被取消(cancelable 值为 true),且 event 中至少有一个事件处理程序调用了 Event.preventDefault() 方法时,返回 false。否则,返回 true。
写在最后
按照 MDN 的说法,由程序触发的事件,还有一个专用名词 合成事件
,表示不是浏览器本身触发的事件。
除了本文例子中的几个 Event 对象外,还有一些其他对象,在使用时可参考 MDN 文档。
用户交互:
鼠标、键盘、触摸交互 MouseEvent
, KeyboardEvent
, TouchEvent
表单与输入:
输入框、表单提交 InputEvent
, SubmitEvent
媒体控制:
音视频播放、设备流 MediaStreamTrackEvent
拖放与剪贴板:
拖拽操作、复制粘贴 DragEvent
, ClipboardEvent
存储与通信:
本地存储、跨文档通信 StorageEvent
, MessageEvent
错误与调试:
脚本错误捕获 ErrorEvent
设备与传感器:
方向、加速度检测 DeviceOrientationEvent
动画与过渡:
CSS 动画/过渡生命周期 AnimationEvent
, TransitionEvent
Web前端入门第 77 问:JavaScript 由程序触发绑定事件的几种方式的更多相关文章
- WEB前端技巧之JQuery为动态添加的元素绑定事件.md
jquery 为动态添加的元素绑定事件 如果直接写click函数的话,只能把事件绑定在已经存在的元素上,不能绑定在动态添加的元素上 可以用delegate来实现 .delegate( select ...
- Javascript绑定事件的两种方式的区别
命名函数 <input type="button" onclick="check()" id="btn"/> <scrip ...
- web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史
秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...
- 基于MVC4+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式
在基于MVC4+EasyUI的Web开发框架里面,大量采用了Jquery的方法,对数据进行请求或者提交,方便页面和服务器后端进行数据的交互处理.本文主要介绍利用Jquery处理数据交互的几种方式,包括 ...
- 使用 JavaScript 的 HTML 页面混合、JavaScript 文件引用和 HTML 代码嵌入 3 种方式在 HTML 页面上打印出“点击我进入到百度首页”的超链接
查看本章节 查看作业目录 需求说明: 使用 JavaScript 的 HTML 页面混合.JavaScript 文件引用和 HTML 代码嵌入 3 种方式在 HTML 页面上打印出"点击我进 ...
- web前端入坑第二篇:web前端到底怎么学?干货资料! 【转】
http://blog.csdn.net/xllily_11/article/details/52145172 版权声明:本文为博主[小北]原创文章,如要转载请评论回复.个人前端公众号:前端你别闹,J ...
- web前端(13)—— 了解JavaScript,JavaScript的引入方式
从本篇博文开始,将进入web前端方便最关键最重要的部分——javascript,学到后面你就知道它真的太重要了 什么是JavaScript JavaScript一种直译式的脚本语言,是一种动态类型.弱 ...
- WEB前端工程师整理的原生JavaScript经典百例
一.原生JavaScript实现字符串长度截取 二.原生JavaScript获取域名主机 三.原生JavaScript转义html标签 四.原生JavaScript时间日期格式替换 Date.prot ...
- Web前端基础怎么学? JavaScript、html、css知识架构图
以前开发者只要掌握 HTML.CSS.JavaScript 三驾马车就能胜任一份前端的工作了.而现在除了普通的编码以外,还要考虑如何性能优化,如何跨端.跨平台实现功能,尤其是 AI.5G 技术的来临, ...
- web前端——实例中学习css,javascript
最近闲暇时候在研究前端的样式和js,以前都是从w3school上看看那些选择器和DOM操作方法很少去实际做demo来研究,做的过程当中才真切感觉到纸上得来终觉浅,看得懂跟能做出东西完全两码事,尤其在定 ...
随机推荐
- web自动化的鼠标操作
有些场景不适合点击或进行某些操作,可运用action类模拟鼠标操作.在操作一个页面元素时有时需要一连串的动作来配合的时候,可以使用action来完成. Actions actions= new Act ...
- webapi里调用grpc
参照:ASP .NET Core 6.0使用Grpc配置服务和调用服务_asp.net core grpc 服务-CSDN博客 demo:https://files.cnblogs.com/files ...
- python 处理word 分页符、分节符
import docx doc1 =docx.Document(r"C:\Users\Administrator\Desktop\test.docx") doc1.paragrap ...
- 【经验】Git|Windows下如何管理和部署多个Git账号的SSH密钥文件
生成 SSH 密钥 先打开一个git窗口,生成ssh密钥. 如果打开的不是git窗口,而是cmd窗口,则需要先切换到C:\Users\用户名\.ssh目录下. 下面这条指令的your_email和yo ...
- QtWidget项目-仿腾讯QQ音乐
本博客主要介绍本人写的个人项目 - QtWidget5 仿腾讯QQ音乐项目. 效果演示 项目详情 源码 Gitee地址:https://gitee.com/run-little-peach/my-qq ...
- C#之Bitmap
SetPixel和GetPixel private void btnC_Click(object sender, RoutedEventArgs e) { OpenFileDialog dia = n ...
- odoo里面的动作
来源:Odoo中的五种action都是继承自ir.actions.actions模型实现的子类,共有五种,下面会一个一个给出具体例子 1.链接Action(ir.actions.act_url):ta ...
- MyBatis常见面试题:通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
MyBatis常见面试题:通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗? Dao接口即Mapper接 ...
- github无法访问问题解决方法
问题描述: 直接使用gtihub.com网址访问github浏览器无响应. 解决办法: 1.登录https://github.com.ipaddress.com/去查询github.com.githu ...
- CentOS7 vsftpd服务搭建与详解
FTP介绍 文件传输协议(File Transfer Protocol,FTP),基于该协议FTP客户端与服务端可以实现共享文件.上传文件.下载文件. FTP 基于TCP协议生成一个虚拟的连接,主要用 ...