JavaScript 中的事件模拟

一、DOM 级别 2 的事件模拟

利用 DOM2 的标准我们可以模拟这些类型的事件:HTMLEvents,MutationEvents,UIEvents 和 MouseEvents。而事件的模拟基本是三步:createEvent,initEvent 和 dispatchEvent。例如我们可以用下面的方式模拟 HTML 事件:

var event = document.createEvent("HTMLEvents");

event.initEvent("focus", true, false);

element.dispatchEvent(event);

其中 HTML 事件包括这些:load,unload,abort,error,select,change,submit,reset,focus,blur,resize,scroll。

而变动事件的模拟的例子如下:

var event = document.createEvent("MutationEvents");

event.initMutationEvent("DOMNodeInserted", true, false, someNode, "","","",0);

element.dispatchEvent(event);

其中变动事件包括这些:DOMSubtreeModified,DOMNodeInserted,DOMNodeRemoved,DOMNodeRemovedFromDocument,DOMNodeInsertedIntoDocument,DOMAttrModified,DOMCharacterDataModified。

上面这两类事件用得不多的,我们经常需要模拟的是鼠标事件。例如:

var event = document.createEvent("MouseEvents");

event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

element.dispatchEvent(event);

initMouseEvent 的 15 个参数中,第一个指该事件的名称,第二个指该事件是否冒泡,而第三个指该事件是否可取消。其它的参数的意义可以参考 DOM2 文档。如果我们只需要模拟该事件而不关心该事件出现的坐标等,可以偷懒用 initUIEvent(这是由于 MouseEvent 对象继承自 UIEvent 对象),如下:

var event = document.createEvent("MouseEvents");

event.initUIEvent("click", true, true, document.defaultView, 0);

element.dispatchEvent(event);

或者更加偷懒地使用 initEvent(因为 UIEvent 对象也是继承自最基本的 Event 对象):

var event = document.createEvent("MouseEvents");

event.initEvent("click", true, true);

element.dispatchEvent(event);

二、DOM 级别 3 的事件模拟

在 DOM3 中,增加了 KeyboardEvent,WheelEvent,CustomEvent 等类型事件的模拟。注意对于事件类型名称 DOM2 中使用复数形式,而 DOM3 中使用单数形式。同时,对于 DOM2 中的 MutationEvents,UIEvents 和 MouseEvents,在 DOM3 中同样可以用单数形式的 MutationEvent,UIEvent 和 MouseEvent(DOM3 中没有 HTMLEvent,只涉及到 FocusEvent)。列个表对比并总结如下:

事件类型 DOM2 的类型名 DOM3 的类型名 事件初始化函数
基本事件 Event initEvent
自定义事件 CustomEvent initCustomEvent
HTML 事件 HTMLEvents initEvent
变动事件 MutationEvents MutationEvent initMutationEvent
UI 事件 UIEvents UIEvent initUIEvent
鼠标事件 MouseEvents MouseEvent initMouseEvent
滚轮事件 WheelEvent initWheelEvent
键盘事件 KeyboardEvent initKeyboardEvent
焦点事件 FocusEvent initFocusEvent

 下面的例子模拟了键盘的 keydown 事件(按下 Shift+a):

event = document.createEvent("KeyboardEvent");

event.initKeyboardEvent("keydown", true, true, document.defaultView, "a", 0, "Shift", 0);

element.dispatchEvent(event);

类似地也可以模拟 keyup 和 keypress 事件。DOM3 标准中的 initKeyboardEvent 函数参数有过改动,这导致各个浏览器的兼容性出现问题。我们可以参考这里的 gist 代码:Cross-browser initKeyboardEvent

三、事件模拟的浏览器支持

Firefox,Chrome,Safari,Opera 支持 DOM2 的事件模拟,但是基本不支持 DOM3 新的事件模拟。而 IE9 支持 DOM2 和 DOM3 的事件模拟,但是 IE8 及其之前的版本完全不支持 DOM2 和 DOM3 的事件模拟。在旧版本的 IE 中可以使用 createEventObject 和 fireEvent 方法实现事件模拟。

我们可以用 document.implementation.hasFeature 方法检测浏览器对这些事件模拟的支持情况。例如:

var hasDOM2HTMLEvents = document.implementation.hasFeature("HTMLEvents", "2.0");

var hasDOM3KeyboardEvent = document.implementation.hasFeature("KeyboadEvent", "3.0");

但实际上,这种方法还是不够可靠,最后还是用特性检测比较好。

参考资料:
[1] DOM Level 2 Events - 1. Document Object Model Events
[2] DOM Level 2 Events - Appendix A: IDL Definitions
[3] DOM Level 3 Events - #events-DocumentEvent-createEvent
[4] DOM Level 3 Events - #event-types
[5] DOM Level 3 Events - #event-interfaces
[6] document.createEvent - Document Object Model (DOM) | MDN
[7] DOM Level 3 Events support in IE9 - IEBlog - Site Home - MSDN Blogs
[8] Internet Explorer: Testing Center #domevents

你可能感兴趣的:(JavaScript)