首页 > 代码库 > JS的事件模型

JS的事件模型

  之前对事件模型还是比较清楚的,许多概念都清晰映射在脑海中。工作之后,一方面使用的
局限性,二是习惯于用框架中的各种事件监听方式,简单即方便,久而久之,事件的一些概念开
始淡出记忆中,就像我现在已经开始淡忘C语言的指针、麦克斯韦方程组、矩阵的变换、最小二乘
法等。知识就像五彩缤纷的鹅卵石铺垫在你前行的道路上,从简单到深刻,从深刻到领悟,一直
助你渐行渐远。回头看看事件模型呗。


一、事件简简介
事件包括:
鼠标事件
键盘事件
框架事件 one rror onresize onscroll等
表单事件事件 onblur onfocus等
剪贴板事件 oncopy oncut onpaste
打印事件 onafterprint onbeforeprint
拖动事件 ondrag ondragenter等
media事件 onplay onpause
动画事件 animationend
过渡事件
其他事件等

事件被封装成对象,包括
目标事件对象
事件监听对象
鼠标事件对象
键盘事件对象等
他们包含了各自的属性和方法,也继承自Event这个对象。具体看你W3C就OK了。
常用方法:
event. preventDefault()//阻止元素默认的行为,如链接的跳转、表单的提交;
event. stopPropagation()//阻止事件冒泡

二、事件的三种模型
1、原始事件模型(DOM0级)
  特点:原始事件模型中,事件发生后没有传播的概念,没有事件流。事件发生,立即处理。
监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。书写方式有两种:

  HTML: <input id=”btn” onclick=”func()” />
js : document.getElementsById(‘btn’).onclick = func

  优点:所有浏览器都兼容

  缺点:
a、逻辑与显示没有分离;
b、相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的。
c、无法通过事件的冒泡、委托等机制等。

  在当前web程序模块化开发以及更加复杂的逻辑状况下,这种方式显然已经落伍了,所以在真
正项目中不推荐使用,平时写点demo倒是可以,速度比较快。

2、IE事件模型
特点:IE是将event对象在处理函数中设为window的属性,一旦函数执行结束,便被置为null
了。
IE的事件模型只有两步,先执行元素的监听函数,然后事件沿着父节点一直冒泡到document。
绑定解除监听函数的方法:
attachEvent( "eventType","handler"),其中evetType为事件的类型,如onclick,注意要加
’on’。
解除事件监听器的方法是 detachEvent("eventType","handler" );
缺点:就是只能IE自己用,太高冷了。

3、 DOM2事件模型
在 W3C 2 级 DOM 事件中规范了事件模型,即 DOM2事件模型。现代浏览器(IE9以下不算)都遵
循了这个规范。
特点:
W3C制定的事件模型中,一次事件的发生包含三个过程:
  a、事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节
          点是否注册了该事件的监听函数,若有则执行。
  b、事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数.
  c、事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册
了该事件的监听函数,有则执行。

   注意:所有的事件类型都会经历事件捕获阶段,但是只有部分事件会经历事件冒泡阶段,例如
submit事件就不会被冒泡。

绑定解除监听函数的方法:
addEventListener("eventType","handler","true|false");其中eventType指事件类型,注意
不要加‘on’前缀,与IE下不同。
第二个参数是处理函数,
第三个即用来指定是否在捕获阶段进 true捕获阶段 false 只有冒泡阶段
监听器的解除也类似:removeEventListner("eventType","handler","true!false");


兼容IE和现代浏览器的事件注册监听写法

var a = document.getElementById(‘XXX‘);
if(a.attachEvent){
    a.attachEvent(‘onclick‘,func);
}
else{//IE9以上和主流浏览器
    a.addEventListener(‘click‘,func,false);
}

现有的框架和类库都会对适应各种浏览器做兼容性的封装,JQuery底层即使用了上面的兼容性写法。

 

三、事件的捕获-冒泡机制
DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和
冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监听函数。

以如下HTML结构为例子,执行流程应该是这样的:

<div id="parent">
       父元素
       <div id="child">子元素</div>
</div>

技术分享

运行一下一目了然。

var parent= document.getElementById(‘parent‘);
	console.dir(parent);
    var child = document.getElementById(‘child‘);
    parent.addEventListener(‘click‘,function(){alert(‘父亲在捕获阶段被点

击‘);},true);//第三个参数为true
    child.addEventListener(‘click‘,function(){alert(‘孩子被点击了‘);},false);
 parent.addEventListener(‘click‘,function(){alert(‘父亲在冒泡阶段被点击

了‘);},false);//第三个参数为false

 

  可以看到,第三个即用来指定是否在捕获阶段进 true捕获阶段,false没有捕获阶段 。
如果不想让事件向上冒泡,可以在监听函数中调用event.stopPrapagation()来完成,后面会有应
用的栗子。

四、事件委托机制

  委托就是把事件监听函数绑定到父元素上,让它的父辈来完成事件的监听,这样就把事情“委托
”了过去。在父辈元素的监听函数中,可通过event.target属性拿到触发事件的原始元素,然后
再对其进行相关处理。

 

五、jQuery中的事件监听方式
  jQuery中提供了四种事件监听方式,分别是bind、live、delegate、on,对应的解除监听的
函数分别是unbind、die、undelegate、off。这几个方法已经对各种浏览器的兼容性进行封装。
具体方法可以查看手册。
注意几点:
jQuery推荐事件的绑定都使使用on方法
jQuery默认事件不在捕获中进行

六、什么是自定义事件
张鑫旭的《js-dom自定义事件》


七、一个简单例子
点击弹窗之外任何地方,弹框关闭。


方法:给body绑定事件,在事件的执行函数里关闭弹框;
给弹框元素绑定点击事件,在事件的执行函数里面组织事件冒泡,即:
event.stopPrapagation();

 

JS的事件模型