一.前言
本章主要介绍JS中的事件,包括事件的一般写法和兼容浏览器的写法。事件的种类等。由于篇幅有限,IE中很多特性就不在本文介绍,很多平时用不到的事件也就请看书啦。
二.事件处理程序
-
DOM0级事件处理程序
每个程序都有自己的事件处理程序,例如onclick。
var btn = document.getElementById('myBtn') btn.onclick = function(){ alert(this.id) //myBtn }
已这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。
可以通过btn.onclick = null
删除事件处理程序。 -
DOM2级事件处理程序
“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。包含三个参数:最后的布尔值参数如果是false,表示在捕获阶段调用事件处理程序。参数为true,表示在冒泡阶段调用事件处理程序。var btn = document.getElementById('myBtn') btn.addEventListener('click',function(){ alert(this.id) },false) btn.addEventListener('click',function(){ alert('hello') },false)
使用DOM2级方法添加事件处理程序的主要好处是可以添加多个时间处理程序。这里为事件添加了两个事件处理程序。这两个事件处理程序会按照添加它们的顺序触发。
通过addEventListener()添加的事件只能使用removeEventListener()来移除。移除时传入的参数与添加处理程序时使用的参数相同。所以使用addEventListener()添加的匿名函数将无法移除。
var btn = document.getElementById('myBtn') btn.addEventListener('click',function(){ alert(this.id) },false) btn.removeEventListener('click',function(){ alert(this.id) },false) //无效,因为是匿名函数
var btn = document.getElementById('myBtn') var handle = function(){ alert(this.id) } btn.addEventListener('click',handle,false) btn.removeEventListener('click',handle,false) //有效删除
-
IE事件处理程序
IE实现与DOM类似的两个方法:attachEvent(),detachEvent()。
attachEvent()与addEventListener()的不同点是当定义多个方法时,是从后往前执行。
-
跨浏览器的事件处理程序
我们定义一个对象,里面定义添加和删除事件的两个方法,用于适应所有浏览器。
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 } }, removeHandler:function(element,type,handler){ if(element.removeEventListener){ element.removeEventListener(type,handler,false) }else if(element.attachEvent){ element.detachEvent('on'+type,handler) }else { element['on'+type] = null } } }
三.事件对象
-
DOM中的事件对象
var btn = document.getElementById('myBtn') btn.onclick = function(event){ alert(event.type) //click }
-
IE中的事件对象
var btn = document.getElementById('myBtn') btn.onclick = function(event){ var event = window.event alert(event.type) //click }
-
跨浏览器的事件对象
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.preventDefalut){ event.preventDefalut() }else { event.returnValue = false } }, removeHandler:function(element,type,handler){ if(element.removeEventListener){ element.removeEventListener(type,handler,false) }else if(element.attachEvent){ element.detachEvent('on'+type,handler) }else { element['on'+type] = null } }, //阻止事件的捕获和冒泡 stopPropagation:function(event){ if(event.stopPropagation){ event.stopPropagation() }else { event.cancelBubble = true } } }
四.事件类型
‘DOM3级事件’规定了几种类型的事件:焦点事件,鼠标事件,滚轮事件等。需要用到的时候查资料即可,常见了我们都知道,在这里我就列举几个不常见但是会用到的事件。
-
UI事件
- load:当页面完全加载后,就会触发。
EventUtil.addHandler(window,'load',function(event){ alert('loaded') })
- unload:这个事件在文档被完全卸载后触发。
EventUtil.addHandler(window,'unload',function(event){ alert('unloaded') }) ```
-
键盘与文本事件
有三个键盘事件:-
keydown:当用户按下键盘上的任意键时触发,如果按住不放的话,会重复触发此事件。
-
keypress:当用户按下键盘上的字符键时触发,如果按住不放的话,会重复触发此事件。
-
keyup:当用户释放键盘上的键时触发。
-
textInput:‘DOM3级事件’新增了一个新事件,当用户在可编辑区域中输入字符时,就会触发这个事件。这个用于替代keypress,但是两个有两个不同。一是任何可以获得焦点的元素都可以触发keypress,但只有可编辑区域才能触发textInput。二是textInput只有用户按下能够输入实际字符的键时才能触发,keypress在按下能用印象文本显示的键时就能触发(如退格键)。
虽然所有元素都支持上述三个事件,但只有在用户通过文本框输入文本时才最常用到。
在用户按下一个键盘上的字符键时,首先触发keydown,紧跟着时keypress,最后释放时是keyup。keydown和keypress都是在文本框发生变化之前被触发的;keyup是在文本框已经发生变化之后触发。 -
-
键码:在发生keydown和keyup事件时,event对象的keyCode属性会包含一个代码。DOM和IE的event对象都支持keyCode属性。
var textbox = document.getElementById('myText') EventUtil.addHandler(textbox,'keyup',function(event){ event = EventUtil.getEvent(event) alert(event.keyCode) })
-
字符编码:发生keypress事件意味按下的键会影响到屏幕中文本的显示。DOM3级事件不再包含charCode属性,而是包含两个新属性:key和char。
key属性是为了取代keyCode而新增的,它的值是一个字符串。按下某个字符键时,key的值就是相应的文本字符(如:S,M)。按下非字符按键时,key的值时相应的按键名(如:‘shift’,‘esc’)。
char属性在按下字符按键时与key值相同,按下非字符按键时为null。
五.内存和性能
-
事件委托
利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。例如:click事件会冒泡到document层次,也就是说,我们可以为整个页面指定一个onclick事件处理程序,而不是给每个可单击的元素分别添加事件处理程序。<ul id = 'myLinks'> <li id = 'doit'> do </li> <li id = 'goit'> go </li> <li id = 'kissit'> kiss </li> </ul> var list = docuemnt.getElementById('myLinks') EventUtil.addHandler(list,'click',function(event){ event = EventUtil.getEvent(event) var target = EventUtil.getTarget(event) switch(target.id){ case 'doit': document.title = 'I do it' break; case 'goit': document.title = 'I will go ' break; case 'kissit': document.title = 'kiss u' break; } })
由于所有的列表项都是这个元素的子节点,而且它们的事件都会冒泡,所以单击事件最终都会被这个函数处理。这种写法可以让内存占用更少,所有用到按钮的事件都可以采用事件委托技术。
-
移除事件处理程序
<div id = 'myDiv'> <input type = 'button' value = 'click me' id = 'myBtn'> </div> <script> var btn = document.getElementById('myBtn') btn.onclick = function(){ ...... docuemnt.getElementById('myDiv').innerHtml = 'hello!' }
上述我们先使用了input标签中的事件,然后将div中的文本变为字符串‘hello’。但是事件处理程序仍然和按钮保持联系,所以会有一系列的麻烦,我们在确定某个元素将被删除,最好手工移除事件处理程序。
btn.onclick = function(){ ...... btn.onclick = null //移除事件处理程序 docuemnt.getElementById('myDiv').innerHtml = 'hello!' }