JavaScript 的事件流模型都有什么,以及怎么阻止他们?
事件流模型有三中
1. 原始事件模型
在原始事件模型中(DOM 0级),事件发生后没有传播的概念,没有事件流。
事件发生,马上处理,完事,就这么简单。
监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。
1. HTML代码中指定属性值:<input type="button" onclik="fn()">
2. js代码中指定属性值:document。getElementsByTagName("input")[0].onclick = fn
- 优点
所有浏览器都兼容
- 缺点
- 逻辑与显示没有分离(结构与行为没有分离)。
- 相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面。
- 无法通过事件的冒泡、委托等机制完成更多事情。
在当前web程序模块化开发以及更加复杂的逻辑状况下,真正项目中不推荐使用,适合写例子,速度快。
2. DOM事件模型
此模型是W3C制定的标准模型(IE6~8除外的浏览器),都按这个标准规范来;
W3C制定的事件模型中,一次事件的发生包含三个过程:
- capturing phase:事件捕获阶段。
事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。
- target phase:事件处理阶段。
事件到达目标元素,执行目标元素的事件处理函数.
- bubbling phase:事件冒泡阶段。
事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行。
所有的事件类型都会经历captruing phase但是只有部分事件会经历bubbling phase阶段,例如submit事件就不会被冒泡。
- 标准的事件监听器的绑定
addEventListener("eventType","handler","true|false")
其中eventType指事件类型,注意不要加‘on’前缀,与IE下不同;
第二个参数是处理函数;
第三个即用来指定是否在捕获阶段进行处理,一般设为false来与IE保持一致,除非你有特殊的逻辑需求。
- 监听器的解除
removeEventListner("eventType","handler","true!false");
3. IE事件模型
IE不把该对象传入事件处理函数,由于在任意时刻只会存在一个事件,所以IE把它作为全局对象window的一个属性
// 用IE8执行下列代码
window.onload = function (){alert(window.event)};// object event
setTimeout(function(){alert(window.event)},2000);// null
// 由此可见IE是将event对象在处理函数中设为window的属性,一旦函数执行结束,便被置为null了。
IE的事件模型只有两步,先执行元素的监听函数,然后事件沿着父节点一直冒泡到document。
- IE模型下的事件监听方式
attachEvent( "eventType","handler")
//其中evetType为事件的类型,如onclick,注意要加’on’
- 解除事件监听器的方法
detachEvent("eventType","handler" )
- 优缺点
IE的事件模型已经可以解决原始模型的三个缺点,但其自己的缺点就是兼容性,只有IE系列浏览器才可以这样写。
总结
以上便是事件的三种模型,我们在开发的时候需要兼顾IE与非IE浏览器,所以注册一个监听器应该这样写:
var a = document.getElementById('a'); if(a.attachEvent){ a.attachEvent('onclick',func); } else{ a.addEventListener('click',func,false); }
一般会借助现有框架或类库已经封装好的,比如jQuery;
- 如果同时出现DOM0和DOM2事件处理程序,那么不同浏览器处理它们的优先级:
chrome/opera/safari等webkit内核的浏览器:DOM级 --> DOM0级
firefox浏览器和IE浏览器(指IE9及以上版本)会将DOM0级事件优先调用:DOM0级 -->DOM级
事件绑定和普通事件有什么区别?
事件绑定是指把事件注册到具体的 DOM 元素之上,
普通事件指的是可以用来注册的事件
- 事件绑定例子
DOM 元素.addEventListener( 事件类型,事件处理函数)
- 普通事件例子
DOM 元素.事件类型 = function(){事件处理函数}
- 对于事件绑定来说,同一个 DOM 元素上面绑定同样的事件类型时,可以绑定多个事件 处理函数,实际解决了多人开发情况下造成的时间处理覆盖的情况(污染);
- 如果使用普通事件来解决这个问题的时候会造成后写的代码将前写的代码进行了重写操作,造成环境污 染。
实际开发的时候可以视情况而定,来选择绑定事件的方式。