`

浅谈Javascript事件模拟

 
阅读更多

事件是用来描述网页中某一特定有趣时刻的,众所周知事件通常是在由用户和浏览器进行交互时触发,其实不然,通过Javascript可以在任何时间触发特定的事件,并且这些事件与浏览器创建的事件是相同的。这就意味着会有适当的事件冒泡,并且浏览器会执行分配的事件处理程序。这种能力在测试web应用程序的时候,是非常有用的,在DOM 3级规范中提供了方法来模拟特定的事件,IE9 chrome FF Opera 和 Safari都支持这样的方式,在IE8及以前的办法的IE浏览器有他自己的方式来模拟事件
a)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对象。
b)鼠标事件模拟
  鼠标事件可以通过创建一个鼠标事件对象来模拟(mouse event object),并且授予他一些相关信息,创建一个鼠标事件通过传给createEvent()方法一个字符串“MouseEvents”,来创建鼠标事件对象,之后通过iniMouseEvent()方法来初始化返回的事件对象,iniMouseEvent()方法接受15参数,参数如下:
  type string类型 :要触发的事件类型,例如‘click’。
  bubbles Boolean类型:表示事件是否应该冒泡,针对鼠标事件模拟,该值应该被设置为true。
  cancelable bool类型:表示该事件是否能够被取消,针对鼠标事件模拟,该值应该被设置为true。
  view 抽象视图:事件授予的视图,这个值几乎全是document.defaultView.
  detail int类型:附加的事件信息这个初始化时一般应该默认为0。
  screenX int类型 : 事件距离屏幕左边的X坐标
  screenY int类型 : 事件距离屏幕上边的y坐标
  clientX int类型 : 事件距离可视区域左边的X坐标
  clientY int类型 : 事件距离可视区域上边的y坐标
  ctrlKey Boolean类型 : 代表ctrol键是否被按下,默认为false。
  altKey Boolean类型 : 代表alt键是否被按下,默认为false。
  shiftKey Boolean类型 : 代表shif键是否被按下,默认为false。
  metaKey Boolean类型: 代表meta key 是否被按下,默认是false。在Windows键盘中是Windows键,在苹果机中是Cmd键,它们将常被用来修改鼠标事件的行为
  button int类型: 表示被按下的鼠标键,默认是零. 
  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,都可以通过相同的方式来实现。
c)键盘事件模拟
  值得注意的是键盘事件已经从DOM2级事件中移出了,起初在DOM2级事件的草案版中,键盘事件是作为草案的一部分的,但在最终版被移出了,FF已经实现了草案版中的键盘事件,值得注意的是在DOM3级事件中实现的键盘事件与DOM2级事件草案版中的键盘事件还是存在很大差异的。
在dom3级事件中创建一个键盘事件对象是通过createEvent()方法,并传入KeyBoardEvent字符串作为参数,对返回的event对象,调用initKeyBoadEvent()方法初始化,初始化键盘事件的参数有以下几个:
  type (string) - 要触发的事件类型,例如“keydown”.
  bubbles (Boolean) — 代表事件是否应该冒泡. 
  cancelable (Boolean) — 代表事件是否可以被取消. 
  view (AbstractView) — 被授予事件的是图. 通常值为:document.defaultView.
  key (string) — 按下的键对应的code.
  location (integer) — 按下键所在的位置. 0 :默认键盘, 1 左侧位置, 2 右侧位置, 3 数字键盘区, 4 虚拟键盘区, or 5 游戏手柄.
  modifiers (string) — 一个有空格分开的修饰符列表.
  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个参数,
  type (string) — 要触发的事件类型,例如“keydown”.
  bubbles (Boolean) — 代表事件是否应该冒泡.
  cancelable (Boolean) — 代表事件是否可以被取消. 
  view (AbstractView) — 被授予事件的是图. 通常值为:document.defaultView.
  ctrlKey (Boolean) — 代表ctrol键是否按下. 默认 false.
  altKey (Boolean) — 代表alt键是否按下. 默认 false.
  shiftKey (Boolean) — 代表shift键是否按下. 默认 false.
  metaKey (Boolean) — 代表meta键是否按下. 默认 false.
  keyCode (integer) — 键按下或释放时键所对应的键码. 默认是0;
  charCode (integer) — 按下的键的字符所对应的ASCII code.是共keypress事件使用的 默认是0.
D)模拟其他事件
鼠标事件和键盘事件是在浏览器中最长被模拟的事件,,但是某些时候同样需要模拟突变事件和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事件是很少在浏览器中用到,因为他们收应用程序的限制。
E)定制DOM事件
在DOM3级事件中定义了一类事件称之为 custom event,我称之为客户事件,客户事件不会原生的被dom触发,而是直接提供,以至于开发者可以创建他们自己的事件,你可以创建一个自己的客户事件,通过调用createEvent('CustomEvent'),对返回的事件对象调用,initCustomEvent()方法,其中传递四个参数type,bubbles,cancelable,detail。ps:小弟对这部分理解有限,在这里只是抛砖引玉。
F)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的事件模拟更容易让人记忆和接受,统一的事件模型可以带来一些便捷。

参考:http://www.cnblogs.com/MrBackKom/archive/2012/06/26/2564501.html

分享到:
评论

相关推荐

    《浅谈JavaScript系列》.pdf

    以下是从《浅谈JavaScript系列》中提炼出的核心知识点。 1. 面向对象编程:JavaScript虽基于对象而非完全的面向对象语言,但通过原型链实现了继承。JavaScript中,对象通过原型继承属性和方法,每个对象都有一个...

    浅谈javascript事件环微任务和宏任务队列原理

    值得注意的是,如果通过`inner.click()`模拟点击,因为没有事件冒泡过程,输出顺序将会不同,这是因为`click`事件直接触发而不会被压入执行栈,所以微任务会先于宏任务执行。 了解事件环、微任务和宏任务的原理,...

    浅谈Javascript面向对象编程

    标题《浅谈Javascript面向对象编程》涉及了JavaScript语言在实现面向对象编程(OOP)方面的核心概念及其灵活运用。接下来,我们详细地梳理一下从给定文件内容中提取的关于JavaScript面向对象编程的知识点。 1. 数据...

    浅谈JavaScript中面向对象技术的模拟

    JavaScript不是纯的面向对象的语言,而是基于对象的语言,对象的继承是以原型函数的形式继承的,很多初学者刚开始接触的时候不太理解,但是JavaScript这种以原型函数的形式实现面向对象技术,不仅是可行的,而且还为...

    浅谈JavaScript中的接口实现

    但问题在于,在JavaScript的世界中,没有内置的创建或实现接口的方法,也没有可以判断一个对象是否实现了与另一个对象相同的一套方法,这使得对象之间很难互换使用,好在JavaScript拥有出色的灵活性,这使得模拟传统...

    浅谈Javascript如何实现匀速运动

    在网页编程中,利用JavaScript模拟匀速运动,通常用于制作动画效果,如元素的位置、透明度、大小等属性的变化。 通过给出的文件内容,我们可以总结出实现匀速运动需要涉及的几个关键知识点: 1. 事件监听:在...

    浅谈Javascript 数组与字典

    尽管如此,对象在JavaScript中仍然广泛地用于模拟字典,尤其在需要较为简单的键值对存储时。 JavaScript数组与字典的灵活性使得它们在Web开发中应用非常广泛,无论是处理动态数据还是实现复杂的逻辑关系,这两种...

    浅谈Javascript数组的使用

    push()和pop()方法允许数组模拟堆栈的行为,分别是向数组尾部添加元素和从数组尾部移除元素。使用delete操作符可以移除数组元素,但会留下一个空位(即undefined)。如果要完全移除元素并且优化数组大小,应该使用...

    浅谈javascript对象模型和function对象

    本文深入浅出地探讨了JavaScript对象模型与function对象的概念与用法,并通过示例代码展示了JavaScript函数的特性。接下来将详细阐述本文提到的关键知识点。 首先,JavaScript中的函数也是对象,这意味着函数可以像...

    浅谈JavaScript实现面向对象中的类

    在JavaScript中,我们可以使用函数来模拟类的定义。通过使用关键字“function”定义一个函数,我们其实就是在创建一个可以被实例化的“类”。这种通过函数模拟的类,可以拥有属性和方法。属性可以是公有属性或私有...

    浅谈Javascript中的对象和继承

    在JavaScript中,类可以通过函数来模拟,如`Person`示例所示: ```javascript function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.run = function() { console.log('...

    浅谈JavaScript超时调用和间歇调用

    `setTimeout()` 的执行时机依赖于JavaScript的事件循环和任务队列,这意味着如果当前执行栈中有其他任务,setTimeout设置的函数会被延迟到当前任务结束后再执行。这与 `setInterval()` 不同,后者会在固定间隔内尽...

    浅谈JavaScript中this的指向更改

    在JavaScript中,没有传统的类继承,但可以通过构造函数的`call`或`apply`来模拟。在例子中,`Calc`构造函数通过`CalcA.call(this)`和`CalcS.call(this)`,使得`Calc`可以继承`CalcA`和`CalcS`的属性和方法。 还有...

    浅谈JavaScript中的作用域和闭包问题

    闭包的使用例子中,我们可以看到,当我们在循环中创建事件处理函数时,如果不使用闭包,循环变量会共享相同的值。这是因为循环结束时变量的值会被最后的迭代结果所覆盖。而使用闭包则可以保持循环每个迭代独立的变量...

    浅谈javascript中的call、apply、bind

    在JavaScript中,`call`...这些方法在JavaScript中广泛应用于继承、模拟类构造函数、控制事件处理函数的上下文等场合,极大地提升了代码的灵活性和可复用性。理解并熟练掌握它们,对于提升JavaScript编程能力至关重要。

    浅谈javascript中new操作符的原理

    为了更好地理解这个过程,我们可以模拟`new`操作符的工作方式,编写一个名为`NEW_OBJECT`的函数,如下所示: ```javascript function NEW_OBJECT(Foo) { var obj = {}; // 创建新对象 obj.__proto__ = Foo....

Global site tag (gtag.js) - Google Analytics