指定为响应特定事件而应执行的某些动作的技术被称为事件处理。
1 事件处理的三要素
1.1 事件源
事件源就是触发事件的对象。如当按钮被鼠标单击时候触发一个事件,那么按钮就称为事件源。事件源也称为事件目标,因为javascript解释引擎将此对象作为事件的目标。
1.2 事件名
当按钮被单击时,实际上不但会触发单击事件,同时也会触发鼠标移动事件,也就是说,一个对象可以触发多个事件,因此必须对事件分别进行处理。这时就需要使用事件名来标识这个事件,事件名一般就是表明将要发生什么事情以及希望响应什么事情的标识。
1.3 响应
当事件发生时,就可以对事件的发生做出一些响应,也就是要执行的步骤。响应一般通过一个函数来完成,函数体内包含了响应要执行的步骤。
2、事件处理的实现
2.1直接使用元素的事件属性
1 <div id="myDiv" οnclick="javascript:handleEvent(event);">点击这里</div> 2 <script type="text/javascript"> 3 function handleEvent(event) { 4 console.log('事件处理'); 5 } 6 </script>
这种方式所有浏览器都支持。
2.2 直接给元素对象添加事件属性
1 <div id="myDiv">点击这里</div> 2 <script type="text/javascript"> 3 function handleEvent(event) { 4 console.log('事件处理'); 5 } 6 var div = document.getElementById('myDiv'); 7 div.onclick = handleEvent; 8 </script>
这种方式支持所有浏览器。
2.3 使用script元素的for和event属性为脚本定义事件处理代码
for属性定义出发事件对象的id值,event属性定义对象触发的事件。
1 <div id="myDiv">点击这里</div> 2 <script for="myDiv" event="onclick"> 3 console.log('事件处理'); 4 </script>
仅IE支持这种方式,不推荐使用。
2.4 使用对象的fireEvent()方法
IE为每个对象都定义了fireEvent()方法,所以也可以使用该方法来触发事件,该方法的语法格式如下:
bFired = object.fireEvent(sEvent [, oEventObject])
参数说明:
- 参数sEventh用来指定事件字符串;
- 参数oEventObject定义一个对象,用于获取event对象的属性。
如果执行成功则返回true,否则返回false。
下面的代码,单击myDiv就可以触发myDiv2的onclick事件。
1 <div id="myDiv" οnclick="javascript:myDiv2.fireEvent('onclick');"></div> 2 <div id="myDiv2" οnclick="javascript:this.innerHTML='被单击了;'"></div>
这实际上是一种委派,W3C使用dispatchEvent()方法来实现相同的效果,但dispatchEvent()方法只有一个sEvent参数。如下面的代码可以实现浏览器兼容。
1 var dispatchEvent = function(elementId, sEvent) { 2 try{ 3 var element = document.getElementById(elementId); 4 if(element.fireEvent) { 5 element.fireEvent('on' + sEvent); 6 } else if(element.dispatchEvent) { 7 var evt = document.createEvent('MouseEvents'); 8 evt.initMouseEvent(sEvent, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 9 element.dispatchEvent(evt); 10 } 11 } catch(e) { 12 13 } 14 }
2.5 使用attachEvent()和detachEvent()方法
attachEvent()方法用于将事件绑定到一个函数上,而detachEvent()方法用于解除这种绑定。
语法格式如下:
target.attachEvent(eventType, listener);
target.detachEvent(eventType, listener);
参数说明:
- 参数eventType表示的是事件类型;
- 参数listener表示监听器,也就是一个监听事件的函数。
如下面的代码实现与前面相同的效果:
1 <div id="myDiv">点击这里</div> 2 <script for="myDiv" event="onclick"> 3 function handleEvent(event) { 4 console.log('事件处理'); 5 } 6 var div = document.getElementById('myDiv'); 7 div.attachEvent('onclick', handleEvent); 8 </script>
上面的代码中使用attachEvent()方法将onclick事件绑定到事件处理函数handleEvent()上,当触发onclick事件时就会调用该函数。
如果想解除绑定,可以使用detachEvent()方法,如下面的代码就解除了上述绑定。
<div id="myDiv">点击这里</div> <script for="myDiv" event="onclick"> function handleEvent(event) { console.log('事件处理'); div.detachEvent('onclick', handleEvent); /*解除绑定*/ } var div = document.getElementById('myDiv'); div.attachEvent('onclick', handleEvent); </script>
当单击DIV元素一次后,将执行detachEvent()方法解除绑定,这样,当再次点击时候就不会执行事件函数了。
但其他浏览器不能使用attachEvent()和detachEvent()方法来实现事件处理,而是使用addEventListener()和removeEventListener()方法来实现。
addEventListener()和removeEventListener()方法的语法格式如下:
target.addEventListener(eventType, listener, useCapture);
target.removeEvetListener(eventType, listener, useCapture);
参数说明:
- target就是事件发生的对象,可以是DOM节点、文档自身、window或者XMLHttpRequest;
- 参数eventType表示的是事件类型;
- 参数listener表示监听器,可以是一个监听事件的函数或一个Javascript对象,不过该对象必须实现EventListener接口,该接口要求一个名为handleEvent(eventType)的方法,该方法有一个描述事件的参数;
- 参数useCapture是一个逻辑值,用来确定监听器是运行于捕获阶段、目标阶段还是冒泡阶段。
如果将useCapture设置为true,则监听器只在捕获阶段和目标阶段处理事件,而不在冒泡阶段处理事件;如果useCapture为false,则监听器只在目标或冒泡阶段处理事件。要在3个阶段都监听事件,可以使用两次addEventListener()方法,一次将useCapture设置为true,一次将其设置为false。
低版本的IE事件模型只支持目标阶段和冒泡阶段,所以,把参数useCapture设置为false就会得到与IE相似的行为。
为了兼容不同浏览器,一般使用下面的代码:
1 /** 2 添加事件监听,兼容IE、firefox和chrome浏览器 3 */ 4 var addEventListener = function(elementId, eventType, listener) { 5 try{ 6 var element = document.getElementById(elementId); 7 if(element.addEventListener) { 8 element.addEventListener(eventType, listener); 9 } else if(element.attachEvent) { 10 element.attachEvent('on' + eventType, listener); 11 } 12 } catch(e) {} 13 }; 14 15 /** 16 解除事件监听,兼容IE、firefox和chrome浏览器 17 */ 18 var removeEventListener = function(elementId, eventType, listener) { 19 try{ 20 var element = document.getElementById(elementId); 21 if(element.removeEventListener) { 22 element.removeEventListener(eventType, listener); 23 } else if(element.detachEvent) { 24 element.detachEvent('on' + eventType, listener); 25 } 26 } catch(e) {} 27 }
与前面两种事件方法相比,事件监听方法的优势在于,对同一个事件可以有多个listener,每一个都调用不同的函数。
如下面的代码可以跨浏览器实现与前面相同的结果:
1 <div id="myDiv">点击这里</div> 2 <script for="myDiv" event="onclick"> 3 function handleEvent(event) { 4 console.log('事件处理'); 5 removeEventListener('myDiv', 'click', handleEvent); 6 } 7 var div = document.getElementById('myDiv'); 8 addEventListener('myDiv', 'click', handleEvent); 9 </script>
3、事件处理
当发生事件时,event对象将作为参数传递给事件侦听器(事件处理函数),使用事件侦听器可以获取对event对象的引用,然后就可以使用event对象的成员获取一些与事件相关的信息,如事件发生时候元素键盘的状态,鼠标指针位置和鼠标按钮状态等。
下面的代码,可以检测是否按住Shift键的同时点击超链接,如果是,则不允许打开超链接。
1 <body οnclick="javascript:cancelLink();"> 2 <script type="text/javascript"> 3 function cancelLink() { 4 if(window.event.srcElement.tagName === 'A' && window.event.shiftKey) { //在IE版本中 5 window.event.returnValue = false; 6 } 7 } 8 </script> 9 <a href="www.google.com">Google</a> 10 </body>
Event对象有很多属性,其中两个最重要的,且都是只读的属性:
- currentTarget属性:该属性返回当前正在使用某个事件侦听器处理事件的目标对象。如用户单击“确认”按钮,则currentTarget属性就返回对该按钮的引用,使用Event.currentTarget.name属性就可以返回该按钮的实例名;
- target属性:该属性也是返回事件目标对象,但此属性也会包含目标下的节点。