深入理解DOM事件机制系列第四篇——事件模拟
前面的话
事件是网页中某个特别的瞬间,经常由用户操作或通过其他浏览器功能来触发。但实际上,也可以使用javascript在任意时刻来触发特定的事件,而此时的事件就如同浏览器创建的事件一样。本文将详细介绍事件模拟
引入
以下面的实际需求为例,来详细说明事件模拟的使用。按钮一的点击效果是弹出1。而我们通过新增按钮二来模拟按钮一的效果
<button id="btn1">按钮一</button> <script> btn1.onclick = function(){alert(1); } </script>
事件复制
通过调用相同的事件处理函数,来完成相同的功能
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> btn1.onclick=function(){alert(1); } btn2.onclick = btn1.onclick; </script>
但是,有一个问题,在不知道按钮一的事件处理函数以及以何种调用形式调用时,这种方法是危险的
下面这种情况将无法正确模拟
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> if(btn1.addEventListener){btn1.addEventListener('click',function(){alert(1);}) }else{btn1.attachEvent('onclick',function(){alert(1);}) } btn2.onclick = btn1.onclick; </script>
click()方法
使用click()方法,则无论使用何种事件处理程序都可以实现模拟效果
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> if(btn1.addEventListener){btn1.addEventListener('click',function(){alert(1);}) }else{btn1.attachEvent('onclick',function(){alert(1);}) } btn2.onclick = function(){btn1.click(); } </script>
虽然click()方法可以完美模拟click事件,但是对于其他事件并没有相应的模拟方法,就需要用到下面要介绍的事件模拟了。好吧,我承认这个引入比较长。但是,我不知道如何再缩短了
模拟机制
事件模拟包括3个部分:创建事件、初始化以及触发事件。某些情况下,初始化与创建事件一起进行。最终,通过dispatchEvent()方法或fireEvent()方法来触发事件
对于不同的事件类型,有不同的创建方法。下面以mouseover事件为例
MouseEvent()
使用MouseEvent()方法可以创建鼠标事件。实际上,MouseEvent()方法在创建事件的同时,也包括了初始化的操作
[注意]IE浏览器和safari浏览器不支持
最后使用dispatchEvent()方法在当前节点上触发指定事件。该方法返回一个布尔值,只要有一个监听函数调用了Event.preventDefault(),则返回值为false,否则为true
[注意]IE8-浏览器不支持
function simulateMouseOver(obj) {var event = new MouseEvent('mouseover', {'bubbles': true,'cancelable': true});obj.dispatchEvent(event); }
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> if(btn1.addEventListener){btn1.addEventListener('mouseover',function(){alert(1);}) }else{btn1.attachEvent('onmouseover',function(){alert(1);}) } function simulateMouseOver(obj) {var event = new MouseEvent('mouseover', {'bubbles': true,'cancelable': true});obj.dispatchEvent(event); } btn2.onmouseover = function(){simulateMouseOver(btn1); } </script>
creatEvent()
在document对象上使用createEvent()方法可以用来创建event对象。这个方法接收一个参数,表示要创建的事件类型的字符串
[注意]IE8-浏览器不支持createEvent()方法
在使用document.createElement创建事件之后,还需要使用与事件有关的信息对其进行初始化,每种不同类型的事件都有不同的初始化方法
事件类型 事件初始化方法 UIEvents event.initUIEvent MouseEvents event.initMouseEvent MutationEvents event.initMutationEvent HTMLEvents event.initEvent Event event.initEvent CustomEvent event.initCustomEvent KeyboardEvent event.initKeyEvent
下面是initMouseEvent()方法的参数,它们与鼠标事件的event对象所包含的属性一一对应。其中,前4个参数对正确地激发事件至关重要,因为浏览器要用到这些参数;而剩下的所有参数只有在事件处理程序中才会用到
[注意]IE8-浏览器不支持initMouseEvent()方法
type(字符串):表示要触发的事件类型,例如"click"
bubbles(布尔值):表示事件是否应该冒泡。为精确地模拟鼠标事件,应该把这个参数设置为true
cancelable(布尔值):表示事件是否可以取消。为精确地模拟鼠标事件,应该把这个参数设置为crue
view(AbstractView):与事件关联的视图。这个参数几乎总是要设置为document.defaultView
detail(整数):与事件有关的详细信息。这个值一般只有事件处理程序使用,但通常都设置为0
screenx(整数):事件相对于屏幕的X坐标
screenY(整数):事件相对于屏幕的Y坐标
clientX(整数):事件相对于视口的X坐标
clientY(整数):事件相对于视口的Y坐标
ctrlKey(布尔值):表示是否按下Ctrl键。默认值为false
altkey(布尔值):表示是否按下了Alt键。默认值为false
shiftKey(布尔值):表示是否按下了Shift键。默认值为false
metaKey(布尔值):表示是否按下了Meta键。默认值为false
button(整数):表示按下了哪一个鼠标键。默认值为0
relatedTarget(对象):表示与事件相关的对象。这个参数只在模拟mouseover或mouseout时使用
【写法一】createEvent()方法使用MouseEvents参数
function simulateMouseOver(obj) {var event = document.createEvent('MouseEvents');event.initMouseEvent('mouseover',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); obj.dispatchEvent(event); }
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> if(btn1.addEventListener){btn1.addEventListener('mouseover',function(){alert(1);}) }else{btn1.attachEvent('onmouseover',function(){alert(1);}) } function simulateMouseOver(obj) {var event = document.createEvent('MouseEvents');event.initMouseEvent('mouseover',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); obj.dispatchEvent(event); } btn2.onmouseover = function(){simulateMouseOver(btn1); } </script>
【写法二】createEvent()方法使用Event参数
function simulateMouseOver(obj) {var event = document.createEvent('Event');event.initEvent('mouseover',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); obj.dispatchEvent(event); }
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> if(btn1.addEventListener){btn1.addEventListener('mouseover',function(){alert(1);}) }else{btn1.attachEvent('onmouseover',function(){alert(1);}) } function simulateMouseOver(obj) {var event = document.createEvent('Event');event.initEvent('mouseover',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); obj.dispatchEvent(event); } btn2.onmouseover = function(){simulateMouseOver(btn1); } </script>
createEventObject()
在IE10-浏览器中可以使用document.createEventObject()方法创建event对象。这个方法不接受参数,结果会返回一个通用的event对象
IE浏览器不支持初始化事件,需要手动为这个对象添加所有必要的信息
IE8-浏览器不支持dispatchEvent()事件。在IE8-浏览器中触发事件需要调用fireEvent()方法,这个方法接受两个参数:事件处理程序的名称和event对象。在调用fireEvent()方法时,会自动为event对象添加srcElement和type属性
function simulateMouseOver(obj) {var event = document.createEventObject();event.bubbles = true;event.cancelable = true;obj.fireEvent('onmouseover',event); }
兼容
下面使用document.createEvent()方法和createEventObject()来实现兼容
function simulateMouseOver(obj) {var event;if(document.createEvent){event = document.createEvent('Event');event.initEvent('mouseover',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); obj.dispatchEvent(event); }else{event = document.createEventObject();event.bubbles = true;event.cancelable = true;obj.fireEvent('onmouseover',event);} }
<button id="btn1">按钮一</button> <button id="btn2">按钮二</button> <script> if(btn1.addEventListener){btn1.addEventListener('mouseover',function(){alert(1);}) }else{btn1.attachEvent('onmouseover',function(){alert(1);}) } function simulateMouseOver(obj) {var event;if(document.createEvent){event = document.createEvent('Event');event.initEvent('mouseover',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); obj.dispatchEvent(event); }else{event = document.createEventObject();event.bubbles = true;event.cancelable = true;obj.fireEvent('mouseover',event);} } btn2.onmouseover = function(){simulateMouseOver(btn1); } </script>
自定义事件
自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件
Event()
最简单的就是使用Event()构造函数
[注意]IE和safari浏览器不支持
<button id="btn">按钮</button> <script> function customEvent(obj){var event = new Event('changeColor');obj.addEventListener('changeColor',function(){this.style.backgroundColor = 'lightblue';})return event; } btn.onclick = function(){this.dispatchEvent(customEvent(this)); } </script>
CustomEvent()
如果需要在触发事件的同时,传入指定的数据,需要使用CustomEvent构造函数生成自定义的事件对象
<button id="btn">按钮</button> <script> function customEvent(obj){var event = new CustomEvent('changeColor', { 'detail': 'hello' });obj.addEventListener('changeColor',function(e){e = e || event;this.style.backgroundColor = 'lightblue';this.innerHTML = e.detail;})return event; } btn.onclick = function(){this.dispatchEvent(customEvent(this)); } </script>
createEvent()
要创建新的自定义事件,可以调用createEvent("CustomEvent")。返回的对象有一个名为initCustomEvent()的方法,接收如下4个参数
type(字符串):触发的事件类型,例如"keydown"
bubbles(布尔值):表示事件是否应该冒泡
cancelable(布尔值):表示事件是否可以取消
detail(对象):任意值,保存在event对象的detail属性中
[注意]IE8-浏览器不支持
<button id="btn">按钮</button> <script> function customEvent(obj){var event = document.createEvent('CustomEvent');event.initCustomEvent('changeColor',true,true,'hello');obj.addEventListener('changeColor',function(e){e = e || event;this.style.backgroundColor = 'lightblue';this.innerHTML = e.detail;})return event; } btn.onclick = function(){this.dispatchEvent(customEvent(this)); } </script>
最后
事件模拟是用来触发自定义的事件函数的,而不是来触发浏览器默认行为的
所以,试图通过事件模拟的形式来触发浏览器默认行为是不可行的。比如点击鼠标右键实现键盘backspace键的删除效果是不可行的
转载于:https://www.cnblogs.com/xiaohuochai/p/5880851.html
深入理解DOM事件机制系列第四篇——事件模拟相关推荐
- 深入理解javascript作用域系列第四篇——块作用域
前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...
- Android 6.0 PM机制系列(四) APK安装需要空间分析
前言 在Android 9.0 PM机制系列(四) APK安装需要空间分析文章中,我们重点分析了Android9.0需要的最小APK安装存储空间大小.结论就是:只要系统空间小于Math.min(get ...
- Android 9.0 PM机制系列(四) APK安装需要空间分析
前言 在PM机制系列前三篇,我们着重分析了安装的整个流程,没有具体到很多细节问题. 这一篇文章我们就会具体到很多细节问题.本篇主要就是围绕一个问题展开: 安装APK到底需要多少空间不会报错INSTAL ...
- UR机器人装箱姿态_UR10 RG2机械臂手臂+RealsenseZR300 机器人手眼标定 系列第四篇
UR10 RG2机械臂手臂+RealsenseZR300 机器人手眼标定 系列第四篇 发布时间:2018-09-18 17:43, 浏览次数:1180 , 标签: UR RG RealsenseZR ...
- 深入理解DOM事件类型系列第六篇——加载事件
前面的话 提到加载事件,可能想到了window.onload,但实际上,加载事件是一大类事件,本文将详细介绍加载事件 load load事件是最常用的一个事件,当页面完全加载后(包括所有图像.java ...
- 深入理解DOM事件类型系列第三篇——变动事件
前面的话 变动(mutation)事件能在DOM中的某一部分发生变化时给出提示,这类事件非常有用,但都只能使用DOM2级事件处理程序,且由于浏览器兼容性不好,所以用的不广泛 删除节点 删除节点时,涉及 ...
- 【转】[C# 基础知识系列]专题四:事件揭秘
引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听到"事件"这个概念的,尤其是写UI的时候,当我们点击一个按钮后VS就会自动帮我们生成一些后台的代码,然 ...
- 深入理解this机制系列第三篇——箭头函数
前面的话 this机制与函数调用有关,而作用域则与函数定义有关.有没有什么是可以将this机制和作用域联系起来的呢?本文将介绍ES6新增的内容--箭头函数 痛点 对于闭包的痛点在于,闭包的this默认 ...
- [C# 基础知识梳理系列]专题四:事件揭秘
引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听到"事件"这个概念的,尤其是写UI的时候,当我们点击一个按钮后VS就会自动帮我们生成一些后台的代码,然 ...
最新文章
- linux 内核互斥体,Linux 内核同步(六):互斥体(mutex)
- 公布.NET 框架库源代码(转)
- java 进程通信框架,MediatR-进程内的消息通信框架
- 【PC工具】常用USB转串口芯片CH340G,驱动安装有可能遇到的问题及解决办法
- pycharm中无法安装scipy、imread、GDAL等库
- java如何将string转换成date_java如何将string类型转为date类型?Java的转型方法
- map比vo效率 mybatis_mybatis-plus插件使用的一些问题
- Frida 基础操作2
- php 自定义加密算法,php自定义加密函数、解密
- 滑动翻页效果_Flutter实现3D效果,一个字,炫!
- MatLab的排序函数-sort
- 撰写oracle-sql-hint的注意事项
- Linux:为什么那么多人讨厌systemd?
- 写bat脚本--2021年5月18日
- 基于matlab指纹识别论文,基于MATLAB的指纹识别算法.doc
- 关于验证码错误的解决办法
- uC/OS信号量Pend和Post都会做些什么
- android动画封装,Android开场动画类完整实现代码
- 【论文翻译】SETR:Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformer
- Word中的TIF图像保存后再打开就模糊了