事件处理程序模型
Javascript与HTML之间的交互式通过事件实现的;它最早提出和使用事件视为分担服务器运算负载的。一般来讲,就是文档或者浏览器中发生的一些特定的交互瞬间。我们一般使用时间处理程序来预定事件,这种方式来源于软件工程中的观察者模式;从而实现了页面行为(js脚本)与页面展示之间的松散耦合。
下面说一声常见的几种事件处理程序:
(1)HTML事件处理程序—嵌入式注册模型
该操作通过指定onclick 特性并将一些 JS 代码作为它的值来进行定义。
需要注意的地方就是 HTML事件中 this 的指向问题
如上的 input 代码当 onclick="alert(this.value)",没有问题会弹出 "Click Me" 的结果。
但是一旦 onclick="showValue()"再定义
function showValue(){
alert(this.value);
}
结果为undefined。因为这里的this 已经指向到window,如果需要将函数定义在外部全局中,并且需要使用到所点击的节点DOM,那么就在HTML的JS代码中传入 this 即可,onclick="showValue(this)",在处理函数。
HTML事件处理程序这种方式有如下几个缺点:
首先,HTML与JavaScript紧密耦合,没有分离,更新与维护困难。
第二,扩展事件处理程序作用域链在不同浏览器中不同。
第三,如果不采用调用函数的方式,而是像例子中那样直接书写代码,那么代码的通用性很差,会使得整站的代码量很大,通用性差。如果提取出来,存放在函数当中,那么,会面临另一个问题——当函数还没有被定义,只是HTML、CSS代码加载完毕,用户进行点击,会完全没有反应。
在诸多不便的情况下,一些IT大牛提出类DOM0事件处理程序的概念,并逐渐盛行,最后有了DOM0 事件处理程序。
DOM0 事件处理程序—传统事件模型
通过JS指定事件处理程序传统方式就是将函数赋给一个事件处理程序属性。简单又有跨浏览器优势。
函数内部的 this 会指向当前元素
删除事件只需要将事件属性置为null 即可。
同样DOM0级事件处理程序也有着自身的缺陷缺点:为同一个元素/标签绑定多个同类型事件的时候(如,为上面的这个p标签绑定3个点击事件),是不被允许的。
同样,在诸多不便的情况下,一些IT大牛提出新的概念,并逐渐成熟,最后有了DOM2 事件处理程序。
DOM2 事件处理程序
DOM 2级事件定义了2个方法,addEventListener和 removeEventListener。参数有三个,处理的事件名,事件函数以及是否是捕获阶段的布尔值。
在此的事件函数是使用匿名函数的方式传入,所以就不能在使用 removeEventListener 来解除绑定了,因为就算传入了一样的匿名函数,也是指向不同的函数,所以希望使用 remove 的,必须在add事件的时候使用变量引用传入。
还有就是对于一个元素的一个属性上可以绑定多个事件,并且是按照绑定的顺序执行的。addEventListener添加的事件只能使用 removeEventListener 来解绑,不能使用 0级事件处理程序的方式来解除事件绑定。
(IE9, FF,Safari, Chrome, Opera 支持 DOM2级)
Event模块包括HTMLEvents模块,MouseEvents模块,UIEvents模块。
HTMLEvents模块提供对Event类型事件的支持:abort,blur,change,erro,focus,load,reset,resize,scroll,select,submit,unload
MouseEvents模块提供对MouseEvent类型事件的支持:click,mousedown,mousemove,mouseout,mouseover,mouseup
UIEvents模块提供对UIEvent类型事件的支持:DOMActivate,DOMFocusIn,DOMFocusOut
Event接口定义了如下属性
· type: 发生的事件类型,如click,mouseover
· target: 发生事件的节点,可能与currentTarget不同
· currentTarget: 当前正在运行时间句柄的节点
· eventPhase: 一个数字,指定当前所处的事件传播过程的阶段。它的值为常量:Event.CAPTURING_PHASE、Event.AT_TARGET、Event.BUBBLING_PHASE
· timeStamp: 一个Date对象,声明了事件何时发生。
· bubbles: 一个布尔值,声明该事件是否在文档树中起泡
· cancelable: 一个布尔值,声明该事件是否有默认动作。
Event接口定义的方法:
· stopPropagation(): 阻止事件传播
· preventDefault(): 阻止执行默认动作
UIEvent接口:
Event接口的子接口,MouseEvent接口的父接口。
定义了两个属性:
· view: 发生事件的Window对象(视图对象)
· detail: 一个数字。提供事件的额外信息。对于click,mousedown,mouseup事件,这个字段代表点击的次数。1代表一次,2代表两次,3代表3 次。(每次点击生成一次事件----detail值为2的鼠标事件之前总有detail值为1的鼠标事件)。对于DOMActivate事件,1表示为正常激活,2表示超级激活。(如双击鼠标或同时按下Shift键和Enter键)
MouseEvent接口的属性:
· button: 一个数字,0--左键,1--中间键,2--右键。
· altKey,ctrlKey,shiftKey,metaKey:
· clientX,clientY: 声明鼠标在浏览器窗口的坐标
· screenX,screenY: 声明鼠标针对屏幕左上角的坐标
· relatedTarget: 引用与事件的目标节点相关的节点。(mouseover--鼠标离开的节点,mouseout--鼠标将进入的节点)
IE事件处理程序—ms特有的事件模型
· IE实现的与DOM中类似的两个方法attachEvent 和 detachEvent 接受两个参数事件处理程序名称和事件处理程序函数。其第一个参数为 on 开头,如onclick,onsubmit等。
·
· 在IE中使用attachEvent与使用DOM0级方法最大的区别是事件处理程序的作用域。DOM0级中事件处理程序会在所属元素的作用域内运行,但是在 attachEvent 方法下,事件处理程序会在全局作用于下运行,this会指向于window。
·
· 在对于编写跨浏览器的代码时,记住这点很重要。
· 还有一个与标准的DOM2级不同的是,在一个元素添加多个事件处理程序的时候,addEventListener是按照绑定的顺序先绑定的先执行原则触发事件处理程序的,但是 attachEvent 是先执行最近绑定的事件的,即执行顺序上与 addEventListener 相反。
·
· 在点击后,先弹出 “Helloworld!”,而后 “Clicked”。
· 几个问题:
· 这种模型仅在IE有效;
· 与传统模型不同,这种模型知识引用而非复制事件监听器,因此在使用this时,引用的将是js函数-window对象,而非附加事件监听器的那个对象;
· 还有就是IE不支持事件捕获,无法制定事件流的捕获阶段所有事件始终都会冒泡除非使用cancelBubble来阻止。
好了这一篇说到这里,下一篇,讲讲跨浏览器处理事件
特别谢谢一下博主的文章:
http://blog.chinaunix.net/uid-26672038-id-3956106.html
http://www.cnblogs.com/lianzi/archive/2011/09/17/2179735.html
http://blog.163.com/[email protected]/blog/static/18046981201311735325175/
谢谢你们的分享