事件
一、事件流:
事件流描述的就是在页面中接收事件的顺序——事件冒泡和事件捕获。
1、事件冒泡:
事件冒泡就是事件开始由最具体的元素然后逐层向上传播到较为不具体的节点,所有现代浏览器都支持事件冒泡;
2、事件委托:
事件捕获的思想是,不太具体的节点应该更早接收事件,而最具体的节点应该最后接收节点;用意在于事件到达预定目标前就捕获到他
由于老版本的浏览器不支持事件捕获所以尽量使用事件冒泡;
3、DOM事件流:
DOM规定的事件流包含三个三阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。真正对事件作出响应的是冒泡阶段,然后事件又返回文档;
二、事件处理程序
响应某个事件的函数叫做事件处理程序;
1、HTML事件处理程序:
这种事件处理程序缺点过多不建议使用
2、DOM0级事件处理程序
on+事件类型
该事件处理程序是在元素的作用域内运行,所以this的指向为当前元素。这种事件处理程序简单具有跨浏览器的优势,但是每个事件类型只能绑定一个事件处理程序,
3、DOM2级事件处理程序
addEventListenner()和removeEventListener(),他们分别是添加事件和移除事件,他们都接收三个参数:要处理的事件名,事件处理函数,表示事件处理函数调用阶段的布尔值(true表示在事件捕获阶段调用事件处理程序,false表示在事件冒泡阶段调用事件处理程序)。DOM2级事件处理程序的主要好处是可以添加多个事件处理程序。通过addEventListener添加的事件处理程序只能通过removeEventListenner来移除。这也意味着匿名函数无法移除;
4、IE事件处理程序
IE实现了类似dom的两个方法:attachEvent和detachEvent,这两个法国法都接收两个参数:事件类型和事件处理函数。
在使用attachEvent()方法时,函数处理程序会在全局作用域中运行,因此this指向window;
5、跨浏览器的事件处理程序
// 适用于各种浏览器绑定事件的方法,包括ie的作用域问题
var handler=function(){
console.log(this);
}
var Events={
addEvents:function(ele,type,handler){
if(ele.addEventListener){
ele.addEventListener(type,handler,false);
}else if(ele.attachEvent){
ele.attachEvent("on"+type,function(){
handler.call(ele);
});
}else{
ele["on"+type]=handler;
}
},
removeEvents:function(ele,type,handler){
if(ele.removeEventListener){
ele.removeEventListener(type,handler,false);
}else if(ele.detachEvent){
ele.detachEvent("on"+type,function(){
handler.call(ele);
});
}else{
ele["on"+type]=null;
}
}
}
Events.addEvents(box1,"click",handler);
</script>
三、事件对象
在触发DOM上的某个事件时,会产生一个事件对象,这个对象包含着与事件有关的所有信息。
1、DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入事件处理程序中。event对象包含于创建它的特定事件有关的属性和方法;
其中就有currentTarget和target这两个属性,他们分别表示当前正在处理事件的那个元素以及目标元素;
在事件处理程序内部,对象this始终指向currentTarget的值,而target则只包含事件的实际目标;
如果直接将事件处理程序绑定在目标元素上,this、currentTarget、target包含相同的值;
2、IE中的事件对象
与DOM不同,要访问IE中的event对象有几种不同的方法,取决于指定事件处理程序的类型;
——在使用DOM0级方法添加事件处理程序时,event对象作为window的属性存在;this指向srcElement(事件目标)
——在使用attachEvent()时,event作为参数被传入事件处理程序中,也可以通过window来访问他;this不指向srcElement
3、跨浏览器的事件对象
虽然DOM和IE中的event对象不同,但是依旧可以拿出跨浏览器的方案来。
var Events={
addEvents:function(ele,type,handler){
if(ele.addEventListener){
ele.addEventListener(type,handler,false);
}else if(ele.attachEvent){
ele.attachEvent("on"+type,function(){
handler.call(ele);
});
}else{
ele["on"+type]=handler;
}
},
getEvent:function(event){
// 这里的函数用于返回event对象的引用,DOM和IE的处理方法不同
return event?event:window.event;
},
getTarget:function(event){
// 这里的函数用于返回事件的目标,检测event对象的target属性
// 或者是IE中的srcElement属性
return event.target||event.srcElement;
},
preventDefault:function(event){
// 这里的函数用于取消事件的默认行为,该属性在IE中用returnValue来控制
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue=false;
}
},
removeEvents:function(ele,type,handler){
if(ele.removeEventListener){
ele.removeEventListener(type,handler,false);
}else if(ele.detachEvent){
ele.detachEvent("on"+type,function(){
handler.call(ele);
});
}else{
ele["on"+type]=null;
}
},
stopPropagation:function(event){
// 用于取消事件冒泡
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble=true;
}
}
};
box1.onclick=function(event){
event=Events.getEvent(event);
var target=Events.getTarget(event);
console.log(event.bubbles);
console.log(event.cancelable);
console.log(event.type);
Events.preventDefault(event);
}
四、事件类型
1、UI事件
ui事件指的是那些不一定与用户有关的操作。
——load:当页面完全加载后再window上面触发
——unload:当页面完全卸载后在window上面触发;
——resize:当窗口或框架的大小变化时在window上或框架上触发;
——scroll:当用户滚动带滚动条的元素时,在该元素上触发;
2、焦点事件
——focusout:在失去焦点的元素上触发;
——focusin:在获得焦点的额元素上触发;
——blur:在失去焦点的元素上触发;
——focus:在获得焦点的元素上触发
3、鼠标与滚轮事件
——click:单击鼠标或者按下回车键是触发;
——dbclick:双击鼠标时触发
——mousedown:按下任意鼠标触发
——mouseenter:鼠标光标从元素外部首次移动到元素范围之内触发
——mouseleave:在位于上方的鼠标光标移动到元素范围之外时触发;
——mousemove:当鼠标指针在元素内部移动时重复触发;
——mouseout:在鼠标指针位于一个元素上方,然后又移动到另一个元素时触发
——mouseover:在鼠标指针位于一个元素外部,首次移入另一个元素边界之内时触发
——mouseup:在用户释放鼠标按钮式触发;
——mousewheel:这个事件跟踪鼠标滚轮;
4、键盘与文本事件
——keydown:按下任意键盘时触发
——keypress:按下字符键是触发
——keyup:释放键盘上的键时触发
——textInput:只有在可编辑区域输入字符时才会触发,注意与keydown的区别
五、事件委托
对“事件处理程序过多”问题的解决就是事件委托,事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。例如,click事件会一直冒泡到document层次,也就是说我们可以为整个页面指定一个onclick事件处理程序,而不必给每个可单击元素添加事件处理程序。
当是事件处理程序越多页面执行起来就越慢,
1、可以通过事件委托来解决;
2、可以在不需要的时候移除事件处理程序;
btn.onclick=function(){
//执行代码
btn.onclick=null;
document.getElmentById("btn").innerHTML="processing";
//首先移除该节点事件处理程序
//然后再设置该节点的innerHTML属性
//这样确保内存可以被再次利用
}