前面的話
事件是網頁中某個特別的瞬間,經常由用戶操作或通過其他瀏覽器功能來觸發。但實際上,也可以使用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鍵的刪除效果是不可行的
文章列表