事件流:
事件流:页面接收事件的顺序。
IE定义的:事件冒泡流(由最具体的元素依次传播到DOM树的最上层的Document)
NetScape定义的:事件捕获流(由不具体的节点依次传播到具体的节点)
DOM事件流:先是捕获阶段,然后是处理目标阶段,最后是事件冒泡阶段。
事件处理程序:
a. HTML事件处理程序:
在HTML中加入事件代码:
事件中的代码可以在独立的JS中,事件代码在执行时,有权访问全局作用域中的任何代码。
缺点:
1.时差问题:
在JS程序还没有具备执行条件时,就执行了事件,这时会出现错误。
2.耦合问题:
HTML与JS代码紧密耦合,使得修改时需要对两者都进行修改。
3.JS引擎不同:
不同的JS引擎对其作用域的扩展方式解析不同,在访问非限定对象成员时会出错。、
b.DOM0级事件处理程序:
每个元素都有自己的事件处理程序属性。
var btn=document.getElementById("click");
btn.onclick=function () {
alert("clicked")
};
DOM0级是元素的方法,因此,事件处理程序是在元素的作用域中执行,程序中的this指向该元素。
该程序会在事件冒泡阶段被处理。
如何取消:btn.onclick=null;
c.DOM2级处理程序:
定义了两个方法:addEventListener()removeEventListener()
3个参数:事件名、事件处理程序的函数、布尔值(true事件捕获阶段处理,false事件冒泡阶段处理)
btn.addEventListener("click",function () {
alert("clicked")
},false);
优点:可以对同一元素定义多个事件,事件会顺序处理
btn.addEventListener("click",function () {
alert("clicked")
},false);
btn.addEventListener("click",function () {
alert(this.id);
},false);
注意:一般在事件冒泡阶段处理,这样可以最大程度兼容浏览器。
删除事件:
利用addEventListener()定义的事件处理程序只能通过removeEventListener()删除。
d. IE事件处理程序(IE Opera)
两个方法:attachEvent()detachEvent(),两个参数:事件类型、事件处理函数
注意:事件处理程序的作用域为全局作用域,而非元素的作用域。所以this为window。
可以定义多个事件处理程序,不过执行顺序相反。
var handler=function () {
alert("clicked")
};
btn.attachEvent("onclick",handler);
btn.detachEvent("onclick",handler);
e.跨浏览器的事件处理程序
利用能力检测对浏览器进行测试,分为三种情况:DOM2级、IE、DOM0级
主要方法:
设置一个对象EventUtil,该对象中保存两个属性:addHandler和removeHandler,两个属性对三种情况进行分类:
var EventUtil={
addHandler:function (element,type,handler) {
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
elseif(element.attachEvent){
element.attachEvent("on"+type,handler);
}
else{
element["on"+type]=handler;
}
},
removeHandler:function (element,type,handler) {
if(element.removeEventListener){
element.removeEventListener(type,handler,false)
}
elseif(element.detachEvent){
element.detachEvent("on"+type,handler)
}
else{
element["on"+type]=null;
}
}
};
调用:
var btn=document.getElementById("button");
var handler=function () {
alert("clicked")
};
EventUtil.addHandler(btn,"click",handler);
EventUtil.removeHandler(btn,"click");
事件对象:event
a. DOM中的事件对象
兼容DOM的浏览器会将event对象传入到事件处理程序中。无论事件处理程序使用的是DOM0还是DOM2级。
var btn=document.getElementById("btn");
btn.onclick=function (event) {
alert(event.type)
};
btn.addEventListener("click",function (event) {
alert(event.type)
},false);
在需要一个事件处理函数处理多个事件时,可以使用type类型,利用switch语句进行指定。
b. IE中的事件对象
1.访问IE中的event方法:
DOM0:window.event
var btn=document.getElementById("btn");
btn.onclick=function () {
var event=window.event;
alert(event.type)
};
2.其他的DOM2IEHTML事件处理程序可以使用event。
c.跨浏览器中的事件对象
在上述的EventUtil对象中加入更多的属性
var EventUtil={
addHandler:function (element,type,handler) {
if(element.addEventListener){
element.addEventListener(type,handler,false);
}
else if(element.attachEvent){
element.attachEvent("on"+type,handler);
}
else{
element["on"+type]=handler;
}
},
getEvent:function (event) {
return event? event:window.event;
},
getTarget:function (event) {
return event.target || event.srcElement;
},
preventDefault:function (event) {
if(event.preventDefault){
event.preventDefault();
}
else{
event.returnValue=false;
}
},
stopPropagation: function (event) {
if(event.stopPropagation){
event.stopPropagation();
}
else {
event.cancelBubble=true;
}
},
removeHandler:function (element,type,handler) {
if(element.removeEventListener){
element.removeEventListener(type,handler,false)
}
else if(element.detachEvent){
element.detachEvent("on"+type,handler)
}
else{
element["on"+type]=null;
}
}
};
使用:
先取得event,再使用其它属性。
varbtn=document.getElementById("btn");
btn.onclick=function (event) {
varevent=EventUtil.getEvent(event);
EventUtil.getEvent(event);
};
事件类型
一:UI事件:
UI不一定与用户操作有关。
1.load事件:
页面完全加载完毕后触发。也可以在图像元素上触发。
EventUtil.addHandler(window,"load",function (event) {
alert("加载完毕");
})
2.unload事件:
页面被完全卸载后触发,如页面切换。
3.resize事件:
浏览器窗口被调整到一个新的高度和宽度时触发。
EventUtil.addHandler(window,"resize",function (event) {
alert("调整高度");
})
4.scroll事件:
元素被滚动时触发
二:焦点事件:
最主要的是focus(元素获得焦点时触发)和blur(元素失去焦点时触发)
三:鼠标与滚轮事件:
9个鼠标事件:
click
mousedown
mouseup
mousemove
mouseenter
mouseleave
mouseout
mouseover
dbclick
1.客户区坐标位置:clientX
clientY
在浏览器视口中的位置(不加滚轮)
在浏览器视口中的位置(不加滚轮)
2.页面坐标位置: pageX pageY
在页面中的位置(加上滚轮)
3.屏幕坐标位置:screenX screenY
相对于电脑屏幕的位置,页面放大缩小也是相对于电脑屏幕
var
div=document.getElementsByTagName("div")[0];
EventUtil.addHandler(div,"click",function
(event) {
var
event=EventUtil.getEvent(event);
alert("CLIENTX:"+event.clientX+"screenX:"+event.screenX);
})
相关元素:
只有mouseover和mouseout才有的属性:
relatedTarget, IE中是fromElement和toElement,
其他
事件该属性为null
对于mouseover,相关元素是失去光标的元素,对于mouseout,相关元素是获得光标的元
素
var
div=document.getElementsByTagName("div")[0];
EventUtil.addHandler(div,"mouseover",function
(event) {
var
event=EventUtil.getEvent(event);
var
target=EventUtil.getTarget(event);
var
related=EventUtil.getRelatedTarget(event);
alert("相关元素:"+event.tagName+"鼠标移入:"+related.tagName);
})
鼠标按钮:
对mousedown和mouseup事件,在其event对象中有button属性
DOM中button属性有3个值:0(左键),1(滚轮),2(右键)
IE中的有8个值,0-7,这么多是没有意义的,用户很少同时按几个键,所以需要将其转换为
0,1,2即可。
在EventsUtil对象中加入getButton属性
"getButton":function
(event) {
if(document.implementation.hasFeature("MouseEvents","2.0")){
return event.button;
}
else{
switch (event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 4:
return 1;
case 2:
case 6:
return 2;
return 2;
}
}
}
var div=document.getElementsByTagName("div")[0];
EventUtil.addHandler(div,"mousedown",function
(event) {
var event=EventUtil.getEvent(event);
var button=EventUtil.getButton(event);
alert("button属性值:"+button);
})
鼠标滚轮事件:
mousewheel事件:其event对象中包含wheelDelta属性,wheelDelta是120的倍数,向前是正
值,向后是负值。
特殊情况:
Opera
9.5之前的版本中,正负号颠倒。
FireFox中的该事件名称为DOMMouseScroll,其属性为detail,detail是3的倍数,向前是负
值,向后是正值。
四:键盘与文本事件:
3个键盘事件:
Keydown:按下任意键触发
Keypress:按下字符键触发,可以影响文本显示的键也会触发(如退格键)
keyup:释放键触发
键盘上的每个键都有对应的键码,其对应的属性为keyCode
textInput事件:DOM3中新增的替代keypress的事件。与keypress的不同:只有在可编辑区
域可以触发textInput事件,并且只有能够输入实际字符的键才能触发。
复合事件:
针对同时按住多个键输出的字符。
变动事件:
DOM2级的变动事件处理的是DOM中的变化。比如删除节点、插入节点时的变化。
五:HTML5事件:浏览器自定义的事件
contextmenu事件:上下文菜单(通过鼠标右击实现)
点击我看菜单
百度
必应
天猫
EventUtil.addHandler(window,"load",function
(event) {
vardiv=document.getElementById("myDiv");
EventUtil.addHandler(div,"contextmenu",function (event) {
event=EventUtil.getEvent(event);
EventUtil.preventDefault(event);
varmenu=document.getElementById("Menu");
menu.style.left=event.clientX+"px";
menu.style.top=event.clientY+"px";
menu.style.visibility="visible";
})
EventUtil.addHandler(document,"click",function (event) {
document.getElementById("Menu").style.visibility="hidden";
})
})
beforeunload事件:当用户关闭该页面时触发对话框,让用户选择是否离开页面。
DOMContentLoaded事件:形成DOM树之后即可触发,而不用等待CSS、JS等的加载。
readystatechange事件:提供与文档或者元素的加载状态有关的信息。可用于加载外部JS和CSS。
pageshow和pagehide事件:在用户使用浏览器的后退和前进时加快页面的转换速度。
haschange事件:在URL的参数列表发生变化时通知开发人员。(在AJAX应用中,开发人员经常利用URL的参数列表保存状态)
六:设备事件:智能手机、平板电脑
orientationchange事件:屏幕的横向与纵向
window.orientation属性包括3个值:
0肖像模式
90向左旋转
-90向右旋转
MozOrientation事件:平面方向的变化。
deviceorientation事件:xyz发生变化
devicemotion事件:检测设备是否往下掉,是否被走着的人拿在手里。
七:触摸与手势事件:
触摸事件:
touchstart
touchmove
touchend
touchcancel
手势事件:两个手指触摸屏幕时触发
gesturestart
gesturechange
gestureend
内存和性能
添加大量的事件处理程序会导致页面的整体运行性能,主要原因为:
1.大量的事件处理程序就会有大量的函数,每个函数都是一个对象,会占用大量的内存。
2.需要事先指定DOM访问次数,延迟了页面的交互就绪事件。
处理方法:
1.事件委托:利用了事件冒泡
原方法:
var item1=document.getElementsByTagName("li")[0];
var item2=document.getElementsByTagName("li")[1];
var item3=document.getElementsByTagName("li")[2];
EventUtil.addHandler(item1,"click",function
(event) {
location.href="http://baidu.com";
});
EventUtil.addHandler(item2,"click",function
(event) {
location.href="http://bing.com";
});
EventUtil.addHandler(item3,"click",function
(event) {
location.href="http://tmall.com";
})
事件委托方法:在DOM树中尽量最高的层次上添加一个事件处理程序。
下面的代码的优点:只添加了一个事件处理程序,只取得了一个DOM元素,占用内存少。
var
item=document.getElementsByTagName("ul")[0];
EventUtil.addHandler(item,"click",function
(event) {
event=EventUtil.getEvent(event);
vartarget=EventUtil.getTarget(event);
switch(target.id){
case"baidu":
location.href="http://baidu.com";
break;
case"bing":
location.href="http://bing.com";
break;
case"tmall":
location.href="http://tmall.com";
break;
}
})
不是所有的事件都适合事件委托方式,适合的事件有:clickmousedown mouseupkeydown keyupkeypress
2.移除事件处理程序
当不需要事件时,需要进行事件处理程序的移除。
哪些情况不需要事件:
a.从文档中移除了带有事件处理程序的元素。
b.将带有事件处理程序的元素被innerHTML删除。
此时应该将事件设为null,btn.onclick=null;
模拟事件:利用JS来触发而非用户操作或者浏览器功能。
1.DOM中的事件模拟
a.模拟鼠标事件
b.模拟键盘事件
c.模拟其他事件
d.自定义DOM事件
方法:创建事件对象,初始化事件对象,触发事件。
2.IE中的事件模拟