DOM事件
事件我们经常用到,用起来也比较简单,今天我们主要聊一下DOM事件流、事件的兼容性、事件代理。
DOM事件流
DOM处理事件的流程
事件传递的3个过程
-
capture phase
:事件的捕获过程;从DOM
树的最顶端,直到捕获到出发这个事件的节点的父元素 -
target phase
:事件的触发过程 -
bubble phase
:事件的冒泡阶段,将会从当前节点的父节点开始,一直冒泡到window
对象
这3个流程由W3C规定,但是在IE的低版本里并没有第一个捕获的过程;
并不是所有事件都有这3个过程,有些事件是没有冒泡的过程,例如页面load
事件没有冒泡过程。
事件兼容性
注册事件、取消注册、触发事件、事件对象和事件源、阻止事件传播、取消默认行为等在IE浏览器中和其他浏览器是有区别的,下面我们逐一来看一下
注册事件
事件的注册经常用到,大家都是比较熟悉的,需要注意的是兼容性的问题。
// IE以外
// type 事件类型
// listener 事件处理函数
//最后一个参数可选的:如果是true那么事件句柄在在捕获节点执行;如果是false则事件句柄在冒泡阶段执行
elem.addaEventListener(type,listener [,useCapture])
// 实例
elem.addEventListener('click',clickhandler,false);
function clickhandler(){
// do something
}
而IE
中是这样的
// IE
// type 事件类型
// listener 事件处理函数
// IE中没有捕获阶段 因此没有第三个参数
elem.attachEvent(type,listener);
// 实例
elem.attachEvent('onclick',handler);//事件名称 含 'on'
function handler(){
// do something
}
我们可以做一个兼容的方法,还比较容易理解的。
function addEvent(elem,type,listener){
if(elem.addEventListener){
elem.addEventListener(type,listener,false);
}
if(elem.attachEvent){
elem.attachEvent('on'+type,listener)
}
}
取消注册
//接受参数和addEventListener一致
//IE以外
elem.removeEventListener(type,listener [,useCapture]);
//IE
elem.detachEvent(type,listener)
触发事件
某些情况下,我们需要手动触发事件
//IE以外
elem.dispatchEvent(type);
//触发button的click事件
button.dispatchEvent('click');
//IE
elem.fireEvent(type);
//触发button的click事件
button.fireEvent('onclick');
事件对象和事件源
当调用事件处理函数时候,会隐形的传入一个对象,这个对象就含有了事件的一些状态和信息
function handler(e){
//获取事件对象
// IE的低版本,事件对象不是通过event传入的,而是放在window对象上面
e = event || window.event;
//获取事件源
//IE下是 srcElement
var target = e.target || e.srcElement;
}
取消默认行为
常规的点击链接会打开,但是有时候只是希望处理自定义的业务逻辑而不是打开,这时我们应该取消默认行为。
function eventHandler(e) {
e = e || window.event;
// 防止默认行为
if (e.preventDefault) {
e.preventDefault();//IE以外
} else {
e.returnValue = false;//IE
//注意:这个地方是无法用return false代替的
}
}
阻止事件传播
有时我们需要阻止事件冒泡
function handler(e){
e = e || window.event;
if(e.stopPropagation){
e.stopPropagation();//IE以外
}else{
e.cancelBubble = true;//IE
}
}
事件代理
ul
下有多个li
,我们想要实现在点击每个li
的时候,都触发click
事件,如果在每个li
上都绑定click
事件,工作量将会很大,且要维护多个函数,性能也比较差。这种情况下,我们应该使用事件代理
//在ul上绑定事件,点击li时,通过冒泡传递到ul上,触发click事件
ul.addEventListener('click',handler,false);
function handler(e){
e = e || window.event;
var targetNode = e.target || e.srcElement;
//判断点击的target子元素的类型来触发相应的事件
if(targetNode.nodeName.toLowerCase() === 'li'){
// dosomething
}
}
事件相关的知识点还是比较清晰的,实际使用时,善用事件代理哦!