您的位置:首页 > Web前端 > JavaScript

Professional javascript For Web Developers 第2版读书笔记第5集event事件2

2010-08-06 17:04 1011 查看
IE环境下的event对象

当以DOM0的方式指派事件处理函数时,event对象是作为window的属性存在的

varbtn=document.getElementById(“myBtn”);
btn.onclick=function(){
varevent=window.event;
alert(event.type);//”click”
};

而如果使用attachEvent方法,则与DOM2下的event一样作为一个单独的参数传入函数中

varbtn=document.getElementById(“myBtn”);
btn.attachEvent(“onclick”,function(event){
alert(event.type);//”click”
});




此种方式下,window.event对象仍然存在,把它作为参数传入是为了使用的方便,IE环境下的event对象依然定义了


一些属性和方法,如下表






returnValue属性类似与DOM2中的preventDefault(),都可以用来取消事件的默认行为

varlink=document.getElementById(“myLink”);
link.onclick=function(){
window.event.returnValue=false;
};


cancelBubble属性对应DOM2中的stopPropagation()方法,来阻止事件冒泡

varbtn=document.getElementById(“myBtn”);
btn.onclick=function(){
alert(“Clicked”);
window.event.cancelBubble=true;
};

document.body.onclick=function(){
alert(“Bodyclicked”);
};


Mouse事件类型的执行顺序

1.mousedown

2.mouseup

3.click

4.mousedown

5.mouseup

6.click

7.dblclick

click和dbclick都受其他mouse事件的影响,如果取消了事件冒泡则可能会是这些事件无法触发

事件的性能问题

每个事件处理函数其实都是对象,它们会占用一定内存;大量的为DOM元素指定事件处理函数会推迟页面的交互。

解决此问题的一种途径是事件代理(eventdelegation)

<ulid=”myLinks”>
<liid=”goSomewhere”>Gosomewhere</li>
<liid=”doSomething”>Dosomething</li>
<liid=”sayHi”>Sayhi</li>
</ul>

varitem1=document.getElementById(“goSomewhere”);
varitem2=document.getElementById(“doSomething”);
varitem3=document.getElementById(“sayHi”);
EventUtil.addHandler(item1,“click”,function(event){
location.href="http://www.wrox.com";
});
EventUtil.addHandler(item2,“click”,function(event){
document.title=“Ichangedthedocument’stitle”;
});
EventUtil.addHandler(item3,“click”,function(event){
alert(“hi”);
});

此例中ul的每个list元素都被绑定了事件处理函数,这种方式不仅代码很中,而且会多占用内存空间。

事件代理的方式如下

varlist=document.getElementById(“myLinks”);
EventUtil.addHandler(list,“click”,function(event){
event=EventUtil.getEvent(event);
vartarget=EventUtil.getTarget(event);
switch(target.id){
case“doSomething”:
document.title=“Ichangedthedocument’stitle”;
break;
case“goSomewhere”:
location.href=“http://www.wrox.com”;
break;
case“sayHi”:
alert(“hi”);
break;
}
});

只指派一个处理函数给ul,函数内部进行判断,因为li都是ul的后代,当后代的事件触发后,会冒泡到父节点,这种方式只访问一个对象,并只注册了一个事件处理函数。

借助与这种思想,如果将事件处理函数绑定在document对象上那是最好不过的了,因为

1.document对象是dom中最先被构造的,事件处理函数可以绑定在任何事件中而不需要等(DOMContentLoadedorload)

2.花费更少的时间绑定事件处理函数,只绑定一个事件处理函数占用较小的DOM对象引用和花费更少的时间

3.对页面来说占用很少的内存

最好的使用事件代理方式的候选事件有click,mousedown,mouseup,keydown,keyupandkeypress

处理性能问题的另外一种途径是当不再需要的时候移除事件处理程序。

因为当DOM中某个元素绑定一个事件处理程序,而这个元素又被移除掉的话,这个对于事件处理程序的引用却一直存在,一般是调用removeChild()orreplaceChild(),但最常见的是使用innerHtml属性替换,指派了事件处理程序后又被innerHTML替换后的元素常常不能正确的被垃圾回收

<divid=”myDiv”>
<inputtype=”button”value=”ClickMe”id=”myBtn”>
</div>
<scripttype=”text/javascript”>
varbtn=document.getElementById(“myBtn”);
btn.onclick=function(){

//dosomething

document.getElementById(“myDiv”).innerHTML=“Processing...”;//Bad!!!
};
</script>

此例中button会被移除,但是button的onclick处理函数间的引用关系仍然存在,这种情况对IE浏览器来说是很不好的情况,因为IE会在内存在为元素和处理函数都分配内存,因此当发生这种情况时,最好手动移除事件处理程序

<divid=”myDiv”>
<inputtype=”button”value=”ClickMe”id=”myBtn”>
</div>
<scripttype=”text/javascript”>
varbtn=document.getElementById(“myBtn”);
btn.onclick=function(){
//dosomething
btn.onclick=null;//removeeventhandler
document.getElementById(“myDiv”).innerHTML=“Processing...”;
};
</script>

如果一直悬挂着事件处理函数,那么在页面unload时可能会有问题,如果事件处理函数在页面unload前没有被清理,有可能一直驻留内存,每次由于点击浏览器导航栏中前进,后退或者刷新可能会频繁的让页面load与unload,这样大量的对象会在内存中创建而得不到释放,因为事件处理程序所占用的内存没有被收回。因此一个好的解决方案是在每次onunload事件中移除所有的事件处理函数,但是需要住的是,用这种方式时,对firefox来说onunload会使页面不会保存在bfcache(这是ff的一个页面缓存机制),因此要小心使用.

事件模拟

1.DOM2事件模拟

首先调用createEvent接受一个参数表示事件类型,可以是以下值

UIEvents—GenericUIevent.MouseeventsandkeyboardeventsinheritfromUIevents.

MouseEvents—Genericmouseevent.

MutationEvents—GenericDOMmutationevent.

HTMLEvents—GenericHTMLevent.

然后对返回的event对象附加相应的事件信息

最后是调用dispatchEvent()方法触发事件,这时就和正常触发的效果一样了。

模拟鼠标事件的话首先创建事件对象,然后返回的对象有个initMouseEvent()方法来附加event对象信息,这个方法有15个参数:

type(string)—Thetypeofeventtofire,suchas“click”.

bubbles(Boolean)—Indicatesiftheeventshouldbubble.Thisshouldbesettotruefor

accuratemouseeventsimulation.

cancelable(Boolean)—Indicatesiftheeventcanbecanceled.Thisshouldbesettotruefor

accuratemouseeventsimulation.

view(AbstractView)—Theviewassociatedwiththeevent.Thisisalmostalwaysdocument

.defaultView.

detail(integer)—Additionalinformationfortheevent.Thisisusedonlybyeventhandlers,

thoughit’stypicallysetto0.

screenX(integer)—Thex-coordinateoftheeventrelativetothescreen.

screenY(integer)—They-coordinateoftheeventrelativetothescreen.

clientX(integer)—Thex-coordinateoftheeventrelativetotheviewport.

clientY(integer)—They-coordinateoftheeventrelativetotheviewport.

ctrlKey(Boolean)—IndicatesiftheCtrlkeyispressed.Thedefaultisfalse.

altKey(Boolean)—IndicatesiftheAltkeyispressed.Thedefaultisfalse.

shiftKey(Boolean)—IndicatesiftheShiftkeyispressed.Thedefaultisfalse.

metaKey(Boolean)—IndicatesiftheMetakeyispressed.Thedefaultisfalse.

button(Integer)—Indicatesthebuttonthatwaspressed.Thedefaultis0.

relatedTarget(Object)—Anobjectrelatedtotheevent.Thisisusedonlywhensimulating

mouseoverormouseout.

其中前面的4个最关键,因为它们是由浏览器使用的,其他的信息只有事件处理函数使用到,target参数

当调用dispatchEvent会自动设置,如:

varbtn=document.getElementById(“myBtn”);
//createeventobject
varevent=document.createEvent(“MouseEvents”);
//initializetheeventobject
event.initMouseEvent(“click”,true,true,document.defaultView,0,0,0,0,0,
false,false,false,false,0,null);
//firetheevent
btn.dispatchEvent(event);

Safari在3版之前不是完全支持鼠标事件initEvent3个参数分别为:事件类型,是否支持冒泡,冒泡能否取消,此时用UIEvent模拟

//hackforSafari2.x
varbtn=document.getElementById(“myBtn”);
//createeventobject
varevent=document.createEvent(“UIEvents”);
//initializetheeventobject
event.initEvent(“click”,true,true);
//assignadditionalinformation

event.view=document.defaultView;
event.detail=0;
event.screenX=0;
event.screenY=0;
event.clientX=0;
event.clientY=0;
event.ctrlKey=false;
event.altKey=false;
event.metaKey=false;
event.shiftKey=false;
event.button=0;
event.relatedTarget=null;
//firetheevent
btn.dispatchEvent(event);

键盘事件在DOM2的草图版本中是有的,可是最终版却移除了,但是firefox却实现了起初的草图版本

模拟的方式为创建一个KeyEvent类型的event对象,然后调用initKeyEvent(),此方法接受10个参数

type(string)—Thetypeofeventtofire,suchas“click”.

bubbles(Boolean)—Indicatesiftheeventshouldbubble.Thisshouldbesettotruefor

accuratemouseeventsimulation.

cancelable(Boolean)—Indicatesiftheeventcanbecanceled.Thisshouldbesettotruefor

accuratemouseeventsimulation.

view(AbstractView)—Theviewassociatedwiththeevent.Thisisalmostalwaysdocument

.defaultView.

ctrlKey(Boolean)—IndicatesiftheCtrlkeyispressed.Thedefaultisfalse.

altKey(Boolean)—IndicatesiftheAltkeyispressed.Thedefaultisfalse.

shiftKey(Boolean)—IndicatesiftheShiftkeyispressed.Thedefaultisfalse.
metaKey(Boolean)—IndicatesiftheMetakeyispressed.Thedefaultisfalse.
keyCode(integer)—Thekeycodeofthekeythatwaspressedorreleased.Thisisusedfor

keydownandkeyup.Thedefaultis0.
charCode(integer)—TheASCIIcodeofthecharactergeneratedfromthekeypress.Thisis

usedforkeypress.Thedefaultis0.

因此火狐模拟的方式为:

//forFirefoxonly
vartextbox=document.getElementById(“myTextbox”);
//createeventobject
varevent=document.createEvent(“KeyEvents”);
//initializetheeventobject
event.initKeyEvent(“keypress”,true,true,document.defaultView,false,false,
false,false,65,65);
//firetheevent
textbox.dispatchEvent(event);

对于其他如safari的浏览器要创建一个更宽泛的event对象,然后指定相应的键盘信息

vartextbox=document.getElementById(“myTextbox”);
//createeventobject
varevent=document.createEvent(“Events”);
//initializetheeventobject
event.initEvent(type,bubbles,cancelable);
event.view=document.defaultView;
event.altKey=false;
event.ctrlKey=false;
event.shiftKey=false;
event.metaKey=false;
event.keyCode=65;
event.charCode=65;
//firetheevent
textbox.dispatchEvent(event);

2.IE环境下的事件模拟

没有initEvent方法,因此需要手动附加信息,因此可以添加额外的信息,同时IE下创建的是一个更宽泛的event对象,可以用来对任意的事件类型进行模拟,fireEvent被调用时,srcElement和type属性自动附加到event对象上

varbtn=document.getElementById(“myBtn”);
//createeventobject
varevent=document.createEventObject();
//initializetheeventobject
event.screenX=100;
event.screenY=0;
event.clientX=0;
event.clientY=0;
event.ctrlKey=false;
event.altKey=false;
event.shiftKey=false;
event.button=0;
//firetheevent
btn.fireEvent(“onclick”,event);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: