下面绑定事件的代码,进行了兼容性处理,能够被所有浏览器支持:
function addEvent(obj,type,handle){ try{ // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本 obj.addEventListener(type,handle,false); }catch(e){ try{ // IE8.0及其以下版本 obj.attachEvent('on' + type,handle); }catch(e){ // 早期浏览器 obj['on' + type] = handle; } } }
这里使用 try{ ... } catch(e){ ... } 代替 if ... else... 语句,避免浏览器出现错误提示。
bindEvent(element, eventName, func) —— 绑定func到element的eventName事件上(不重复绑定)
unBindEvent(element, eventName, func) —— 删除element上的eventName事件上的func函数。
下面是这两个函数的源码:
// ---------- 事件绑定与删除绑定 ---------- // function bindEvent(element, eventName, func) { var events = element['the'+eventName]; //用于保存某个事件序列 if(!events) { //如果不存在一个序列,则创建它,并加入HTML标记当中的onEvent = function(){}形式的绑定 events = element['the'+eventName] = []; if (element['on'+eventName]) { events.push(element['on'+eventName]); } } //检测是否为重复绑定 for(var i=0; i<events.length; i++) { if(events[i] === func) { flag = true; break; } } // 非重复绑定,则加入该函数事件 if(i >= events.length) { events.push(func); } // 重新定义这个事件的执行方式 element['on'+eventName] = function(event) { event = event || (function() { //修复IE的事件对象 var e = window.event; e.preventDefault = function() { e.returnValue = false; } e.stopPropagation = function() { e.cancelBubble = true; } //根据需要继续修复 return e; })(); //顺序执行这些函数 for(var i=0; i<events.length; i++) { events[i].call(element, event); } } } // 删除事件绑定 function unBindEvent(element, eventName, func) { var events = this['the'+eventName]; //如果不存在一个事件序列 if(!events) { return false; } //检测该函数是否存在该事件序列当中 for(var i=0; i<events.length; i++) { if(func === events[i]) { [].splice.call(events, i, 1); return true; } } // 函数不存在该事件序列当中 return false; }
该事件绑定函数具有如下特点:
1、在事件函数中,this指向的是当前元素
2、每个事件其实是一个有序列,按顺序执行这个序列。
3、正确的传递了event对象。对于event对象在W3C标准与IE中的不同之处可以做出修复,本例修复了事件冒泡与阻止默认行为。
4、本机测试通过IE、Firefox、Chrome、Opera、Safari(可以说通用主流浏览器)
5、支持删除事件绑定
当然,还得拿来做一个测试,下面是测试的代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <style type="text/css"> #test {background-color: #f00; } </style> <script type="text/javascript" src="event.js"></script> <script type="text/javascript"> bindEvent(window, 'load', function() { var ul = document.getElementById("test"); var a = document.getElementById("baidu"); bindEvent(ul, 'click', function(e){ alert("我是" + this + "元素, 你点击了我!"); }); bindEvent(a, 'click', function(e) { alert("我是" + this + ",你点击了我!"); }); }); </script> </head> <body> <ul id="test"> <p class="t">Hello,world!</p> <p>Hello,<a href="http://www.baidu.com" id="baidu">百度</a>!</p> <li id="haha" class="t">afasdfsa</li> <li>sfk</li> <li class="t">sdklfajsfjk</li> <li>end</li> <li class="te">of</li> </ul> <ol id="test2"> <li class="t">附加的第一项</li> <li class="t">附加的第二项</li> <li class="t">附加的第三项</li> </ol> </body> </html>
首先,点击红色的UL试试看 —— 将预期弹出:你好,我是HTMLUListElement元素,你点击了我!
好的,再点一下其中的百度链接 ——
预期弹出:你好,我是http://www.baidu.com/,你点击了我!
非预期弹出:你好,我是HTMLULlistElement元素,你点击了我?
为什么非预期弹出?——对,这就是事件的冒泡,当我们点击百度的链接后,该事件将产生冒泡,过程如:<a> -- <li> -- <ul> -- <body> -- document。而ul我们绑定了一个单击事件,所以这时将触发其click事件,而出了非预期弹出。
那么如何阻止?在绑定百度链接的函数体后追加一行:e.stopPropagation(),再次测试:非预期弹出已经没有了。
如果我只想在点击百度链接时,弹出对话框,而不跳转到百度去呢?在绑定百度链接的函数体再次追加一行:e.preventDefault();
测试完毕!具有怀疑精神的朋友可以Copy之后,另做其它测试!!!!
转载自web前端开发