文章出處

前面的話

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


文章列表


不含病毒。www.avast.com
全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()