《前端》淺談Javascript事件模擬(事件解釋1)

事件通常是在由用戶和瀏覽器進行交互時觸發,其實不然,通過Javascript可以在任何時間觸發特定的事件,並且這些事件與瀏覽器創建的事件是相同的。這就意味着會有適當的事件冒泡,並且瀏覽器會執行分配的事件處理程序。這種能力在測試web應用程序的時候,是非常有用的,在DOM 3級規範中提供了方法來模擬特定的事件,IE9 chrome FF Opera 和 Safari都支持這樣的方式,在IE8及以前的辦法的IE瀏覽器有他自己的方式來模擬事件。


1、Dom 事件模擬

可以通過document上的createEvent()方法,在任何時候創建事件對象。

此方法只接受一個參數,即要創建事件對象的事件字符串。

在DOM2 級規範上所有的字符串都是複數形式,在DOM 3級事件上所有的字符串都採用單數形式,所有的字符串如下:
  UIEvents:通用的UI 事件,鼠標事件鍵盤事件都是繼承自UI事件,在DOM 3 級上使用的是 UIEvent。
  MouseEvents:通用的鼠標事件,在DOM 3 級上使用的是 MouseEvent。
  MutationEvents:通用的突變事件,在DOM 3 級上使用的是 MutationEvent。
  HTMLEvents:通用的HTML事件,在DOM3級上還沒有等效的。
注意,ie9是唯一支持DOM3級鍵盤事件的瀏覽器,但其他瀏覽器也提供了其他可用的方法來模擬鍵盤事件。

一旦創建了一個事件對象,就要初始化這個事件的相關信息,每一種類型的事件都有特定的方法來初始化。

在創建完事件對象之後,通過dispatchEvent()方法來將事件應用到特定的dom節點上,以便其支持該事件。這個dispatchEvent()事件,支持一個參數,就是你創建的event對象。


2、鼠標事件模擬

鼠標事件可以通過創建一個鼠標事件對象來模擬(mouse event object),並且授予他一些相關信息。

創建一個鼠標事件通過傳給 createEvent()方法一個字符串“MouseEvents”,來創建鼠標事件對象。

之後通過 iniMouseEvent() 方法來初始化返回的事件對象,iniMouseEvent()方法接受15個參數,參數如下:

  1. type string類型 :要觸發的事件類型,例如‘click’。
  2. bubbles Boolean類型:表示事件是否應該冒泡,針對鼠標事件模擬,該值應該被設置爲true。
  3. cancelable bool類型:表示該事件是否能夠被取消,針對鼠標事件模擬,該值應該被設置爲true。
  4. view 抽象視圖:事件授予的視圖,這個值幾乎全是document.defaultView.
  5. detail int類型:附加的事件信息這個初始化時一般應該默認爲0。
  6. screenX int類型 : 事件距離屏幕左邊的X座標
  7. screenY int類型 : 事件距離屏幕上邊的y座標
  8. clientX int類型 : 事件距離可視區域左邊的X座標
  9. clientY int類型 : 事件距離可視區域上邊的y座標
  10. ctrlKey Boolean類型 : 代表ctrol鍵是否被按下,默認爲false。
  11. altKey Boolean類型 : 代表alt鍵是否被按下,默認爲false。
  12. shiftKey Boolean類型 : 代表shif鍵是否被按下,默認爲false。
  13. metaKey Boolean類型: 代表meta key 是否被按下,默認是false。
  14. button int類型: 表示被按下的鼠標鍵,默認是零.
  15. relatedTarget (object) : 事件的關聯對象.只有在模擬mouseover 和 mouseout時用到。

值得注意的是,initMouseEvent() 的參數直接與 event 對象相映射,其中前四個參數是由瀏覽器用到,只有事件處理函數用到其他的參數,當事件對象作爲參數傳給 dispatch() 方式,target屬性將會自動被賦上值。下面是一個例子,

  var btn = document.getElementById(“myBtn”);
  var event = document.createEvent(“MouseEvents”);
  event.initMouseEvent(“click”, true, true, document.defaultView, 0, 0, 0, 0, 0,false, false, false, false, 0, null);
  btn.dispatchEvent(event);

在DOM實現的瀏覽器中,所有其他的事件都包括dbclick,都可以通過相同的方式來實現。


3、鍵盤事件模擬

  值得注意的是鍵盤事件已經從DOM2級事件中移出了,起初在DOM2級事件的草案版中,鍵盤事件是作爲草案的一部分的,但在最終版被移出了,FF已經實現了草案版中的鍵盤事件,值得注意的是在DOM3級事件中實現的鍵盤事件與DOM2級事件草案版中的鍵盤事件還是存在很大差異的。
在dom3級事件中創建一個鍵盤事件對象是通過 createEvent() 方法,並傳入 KeyBoardEvent 字符串作爲參數,對返回的 event對象,調用 initKeyBoadEvent() 方法初始化,初始化鍵盤事件的參數有以下幾個:

  1. type (string) - 要觸發的事件類型,例如“keydown”.
  2. bubbles (Boolean) — 代表事件是否應該冒泡.
  3. cancelable (Boolean) — 代表事件是否可以被取消.
  4. view (AbstractView) — 被授予事件的是圖. 通常值爲:document.defaultView.
  5. key (string) — 按下的鍵對應的code.
  6. location (integer) — 按下鍵所在的位置. 0 :默認鍵盤, 1 左側位置, 2 右側位置, 3 數字鍵盤區, 4 虛擬鍵盤區, or 5 遊戲手柄.
  7. modifiers (string) — 一個有空格分開的修飾符列表.
  8. repeat (integer) — 一行中某個鍵被按下的次數.

請注意的是,在DOM3事件中,費掉了keypress事件,因此按照下面的方式,你只能模擬鍵盤上的keydown 和 keyup事件。

  var textbox = document.getElementById(“myTextbox”),event;
    if (document.implementation.hasFeature(“KeyboardEvents”, “3.0”)){
      event = document.createEvent(“KeyboardEvent”);
      event.initKeyboardEvent(“keydown”, true, true, document.defaultView, “a”,0, “Shift”, 0);
    }
    textbox.dispatchEvent(event);

在FF下,允許你通過使用document.createEvent('KeyEvents'),這種方式來創建鍵盤事件,初始化的方法爲initKeyEvent(),這個方法接受10個參數,

  1. type (string) — 要觸發的事件類型,例如“keydown”.
  2. bubbles (Boolean) — 代表事件是否應該冒泡.
  3. cancelable (Boolean) — 代表事件是否可以被取消.
  4. view (AbstractView) — 被授予事件的是圖. 通常值爲:document.defaultView.
  5. ctrlKey (Boolean) — 代表ctrol鍵是否按下. 默認 false.
  6. altKey (Boolean) — 代表alt鍵是否按下. 默認 false.
  7. shiftKey (Boolean) — 代表shift鍵是否按下. 默認 false.
  8. metaKey (Boolean) — 代表meta鍵是否按下. 默認 false.
  9. keyCode (integer) — 鍵按下或釋放時鍵所對應的鍵碼. 默認是0;
  10. charCode (integer) — 按下的鍵的字符所對應的ASCII code.是共keypress事件使用的 默認是0.

4、模擬其他事件

鼠標事件和鍵盤事件是在瀏覽器中最長被模擬的事件,但是某些時候同樣需要模擬突變事件和HTML事件。

可以用 createEvent('MutationEvents'), 來創建一個突變事件對象,

可以用 initMutationEvent() 來初始化這個事件對象,參數包括type, bubbles, cancelable, relatedNode, prevValue,
newValue, attrName, 和attrChange.可以採用下面的方式來模擬一個突變事件:

  var event = document.createEvent('MutationEvents');
  event.initMutationEvent(“DOMNodeInserted”, true, false, someNode, “”,””,””,0);
  target.dispatchEvent(event);

對於HTML事件,直接上代碼。

  var event = document.createEvent(“HTMLEvents”);
  event.initEvent(“focus”, true, false);
  target.dispatchEvent(event);

對於突變事件和HTML事件是很少在瀏覽器中用到,因爲他們受應用程序的限制。


5、定製DOM事件

在DOM3級事件中定義了一類事件稱之爲 custom event,我稱之爲客戶事件,客戶事件不會原生的被dom觸發,而是直接提供,以至於開發者可以創建他們自己的事件,你可以創建一個自己的客戶事件,通過調用createEvent('CustomEvent'),對返回的事件對象調用,initCustomEvent()方法,其中傳遞四個參數type,bubbles,cancelable,detail。ps:小弟對這部分理解有限,在這裏只是拋磚引玉。


6、IE中的事件模擬

從IE8,以及更早版本的IE,都在模仿DOM模擬事件的方式:創建事件對象,初始化事件信息,之後觸發事件。當然IE在完成這幾個步驟的過程是不同的。
首先不同於dom中創建event對象的方法,IE採用document.createEventObject()方法,並且沒有參數,返回一個通用的事件對象,接下來要對返回的event對象賦值,此時ie並沒有提供初始化函數,你只能採用物理方法一個一個的賦值,最後在目標元素上調用fireEvent()方法,參數爲兩個:事件處理的名稱和創建的事件對象。當fireEvent方法被調用的時候,event對象的srcElement和type屬性將會被自動賦值,其他將需要手動賦值。請看下面的例子:

  var btn = document.getElementById(“myBtn”);
  var event = document.createEventObject();
  event.screenX = 100;
  event.screenY = 0;
  event.clientX = 0;
  event.clientY = 0;
  event.ctrlKey = false;
  event.altKey = false;
  event.shiftKey = false;
  event.button = 0;
  btn.fireEvent(“onclick”, event);

個例子創建了一個事件對象,之後通過一些信息初始化該事件對象,注意事件屬性的賦值是無序的,對於事件對象來說這些屬性值不是很重要,因爲只有事件句柄對應的處理函數(event handler)會用到他們。對於創建鼠標事件、鍵盤事件還是其他事件的事件對象之間是沒有區別的,因爲一個通用的事件對象,可以被任何類型的事件觸發。
  值得注意的是,在Dom的鍵盤事件模擬中,對於一個keypress模擬事件的結果不會作爲字符出現在textbox中,即使對應的事件處理函數已經觸發。
  與DOM事件模擬相比,個人覺得IE的事件模擬更容易讓人記憶和接受,統一的事件模型可以帶來一些便捷。

本博客從今日起停止更新,後續的文章將會發布在新的博客mrbackkom.github.io

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章