// 事件绑定分为两种:
// 一种是传统事件绑定(内联模型/脚本模型);上一章内容;
// 一种是现代事件绑定(DOM2级模型);现代事件绑定在传统事件绑定基础上提供了更强大的功能;
1 // 脚本模型将一个函数赋值给一个事件处理函数; 2 var box = document.getElementById('box'); // 获取元素; 3 box.onclick = function(){ // 元素点击触发事件; 4 alert('Lee'); 5 } 6 7 // 问题一:一个事件处理函数触发两次事件; 8 window.onload = function(){ // 第一组程序; 9 alert('Lee');10 }11 window.onload = function(){ // 第二组程序;12 alert('Mr.Lee');13 }14 // PS:当两组程序同时执行的时候,后面一个会把前面一个完全覆盖;15 // 导致前面的window.onload完全失效了;16 // 解决方案:17 window.onload = function(){ // 第一组事件处理程序,会被覆盖;18 alert('Lee');19 }20 if(typeof window.onload == 'function'){ // 判断之前是否有window.onload;21 var saved = null; // 创建一个保存器;22 saved = window.onload; // 把之前的window.onload保存起来;23 }24 window.onload = function(){ // 下一个要执行的事件;25 // saved()=window.onload = function26 if(saved)saved(); // 判断之前是否有事件,如果有则先执行之前保存的事件;27 alert('Mr.Lee'); // 执行本事件的代码;28 }
// 问题二:事件切换器 box.onclick = boBlue; // 第一次执行toBlue(); function toRed(){ this.className = 'red'; this.onclick = toBlue; // 第三次执行roBlue(),然后来回切换; } function toBlue(){ this.className = 'blue'; this.onclick = toRed; // 第二次执行toRed(); } // 这个切换器在扩展的时候,会出现一些问题: 1.如果增加一个执行函数,那么会被覆盖; box.onclick = toAlert; // 被增加的函数; box.onclick = toBlue; // toAlert被覆盖了; 2.如果解决覆盖问题,就必须包含同时执行; box.onclick = function(){ // 包含进去,但可读性降低; toAlert(); // 第一次不会被覆盖,但第二次又被覆盖; toBlue.call(this); // 还必须把this传递到切换器里; }
1 // 综上三个问题:覆盖问题/可读性问题/this传递为题; 2 // 我们创建一个自定义事件处理函数; 3 function addEvent(obj,type,fn){ // 取代传统事件处理函数; 4 var saved = null; // 保存每次触发的事件处理函数; 5 if(typeof obj['on'+type] == 'function'){// 判断是不是存在事件; 6 saved = obj['on'+type]; // 如果有,保存起来; 7 } 8 obj['on'+type] = function(){ // 然后执行; 9 if(saved)saved(); // 执行上一个;10 fn.call(this); // 执行函数,把this传递进去;11 }12 }13 addEvent(window,'load',function(){14 alert('Lee'); // 可以执行;15 });16 addEvent(window.'load',function(){17 alert('Mr.Lee'); // 可以执行;18 })19 20 // 用自定义事件函数注册到切换器上查看效果:21 addEvent(window,'load',function(){22 var box = document.getElementById('box');23 addEvent(box,'click',toBlue);24 });25 function toRed(){26 this.className = 'red';27 addEvent(this,'click',toBlue);28 }29 function toBlue(){30 this.className = 'blue';31 addEvent(this,'click',toRed);32
// "DOM2级事件"定义了两个方法,用于添加事件和删除事件的处理程序:addEventListener()和removeEventListener();
1 // 所有DOM节点中都包含这两个方法,并且它们都接收3个参数:事件名/函数/冒泡或捕获的布尔值(true表示捕获,false表示冒泡); 2 window.addEventListener('load',function(){ 3 alert('Lee'); 4 },false); 5 window.addEventListener('load',function(){ 6 alert('Mr.Lee'); 7 },false); 8 // PS:W3C的事件绑定好处:1.不需要自定义了;2.可以屏蔽相同的函数;3.可以设置冒泡和捕获; 9 window.addEventListener('load',init,false); // 第一次执行了;10 window.addEventListener('load',init,false); // 第二次被屏蔽了;11 function init(){12 alert('Lee');13 }14 15 // 事件切换器16 window.addEventListener('load',function(){17 var box = document.getElementById('box');18 box.addEventListener('click',function(){ // 不会被覆盖/误删;19 alert('Lee');20 },false);21 box.addEventListener('click',toBlue,false); // 引入切换;22 },false);23 24 function toRed(){25 this.className = 'red';26 this.removeEventListener('click',toRed,false); // 移除事件处理函数;27 this.addEventListener('click',toBlue,false); // 添加需要切换的事件处理函数; 28 }29 30 function toBlue(){31 this.className = 'blue';32 this.removeEventListener('click',toBlue,false);33 this.addEventListener('click',toRed,false);34 }35 36 // 设置冒泡和捕获阶段37 document.addEventListener('click',function(){38 alert('document');39 },true); // 设置为捕获;40 41 document.addEventListener('click',function(){42 alert('Lee');43 },false); // 设置为冒泡;
// IE中实现了与DOM中类似的两个方法:attachEvent()和detachEvent();
// 这两个方法接收相同的参数:事件名和函数;
1 // 在使用这两组函数的时候,区别: 2 // 1.IE不支持捕获,只支持冒泡; 3 // 2.IE添加事件不能屏蔽重复的函数; 4 // 3.IE中的this指向的是window而不是DOM对象; 5 // 4.在传统事件上,IE是无法接受到event对象的;但使用了attachEvent()却可以; 6 window.attachEvent('onload',function(){ 7 var box = document.getElementById('box'); 8 box.attachEvent('onclick',toBlue); 9 });10 11 function toRed(){12 var that = window.event.srcElement;13 that.className = 'red';14 that.detachEvent('onclick',toRed);15 that.attachEvent('onclick',toBlue);16 }17 18 function toBlue(){19 var that = window.event.srcElement;20 that.className = 'blue';21 that.detachEvent('onclick',toBlue);22 that.attachEvent('onclick',toRed);23 }24 // PS:IE不支持捕获;25 // IE不能屏蔽;26 // IE不能传递this,可以call过去;27 28 // 在传统绑定上,IE是无法像W3C那样通过传参接受event对象;但如果使用了attachEvent()却可以;29 box.onclick = function(evt){30 alert(evt); // undefined;31 }32 33 box.attachEvent('onclick',function(evt){34 alert(evt); // object;35 alert(evt.type); // click;36 });37 38 // 兼容IE和W3C的事件切换器函数;39 function addEvent(obj,type,fn){ // 添加事件处理程序兼容;40 if(obj.addEventListener){41 obj.addEventListener(type,fn);42 }else if(obj.attachEvent){43 obj.attachEvent('on'+type,fn);44 }45 }46 47 function removeEvent(obj,type,fn){ // 移除事件处理程序兼容;48 if(obj.removeEventListener){49 obj.removeEventListener(type,fn);50 }esle if(obj.detachEvent){51 obj.detachEvent('on'+type,fn);52 }53 }54 55 function getTarget(evt){ // 得到事件目标;56 if(evt.target){57 return evt.target;58 }else if(window.event.srcEleemnt){59 return window.event.srcElement;60 }61 }
1 1.relatedTarget 2 // 这个属性可以在mouSEOver和mouseout事件中获取从哪里移入和从哪里移出的DOM对象; 3 box.onmouseover = function(evt){ // 鼠标移入box; 4 alert(evt.relatedTarget); // 获取移入box之前的那个元素; 5 } 6 box.onmouseout = function(evt){ // 鼠标移出box; 7 alert(evt.relatedTarget); // 获取移出box之后到的那个元素; 8 } 9 10 // IE提供了两组与之对应的属性:fromElement和toElement;11 // 兼容函数12 function getEarget(evt){13 var e = evt || window.event; // 得到事件对象;14 if(e.srcElement){ // 如果支持srcElement,表示IE;15 if(e.type == 'mouseover'){ // 如果是over事件;16 return e.fromeElement; // 就使用from;17 }else if(e.type == 'mouseout'){ // 如果是out;
新闻热点
疑难解答