严格来说,有2中不同的模型:W3C模型和微软模型,除IE之外W3C模型支持所有的现代浏览器,而微软模型只支持IE,使用W3C模型的代码如下:
// 格式:target.addEventListener( type, function, useCapture ); // 例子: var myIntro = document.getElementById(‘intro‘);myIntro.addEventListener(‘click‘, introClick, false);
使用IE模型的代码如下:
// 格式: target.attachEvent ( ‘on‘ + type, function ); // 例子: var myIntro = document.getElementById(‘intro‘);myIntro.attachEvent(‘onclick‘, introClick);
introClick的代码如下:
function introClick() { alert(‘You clicked the paragraph!‘); }
事实上,要做出通用的话,我们可以自定义一个函数以支持跨浏览器:
function addEvent(elem, type, fn) { if (elem.attachEvent) { elem.attachEvent(‘on‘ + type, fn); return; } if (elem.addEventListener) { elem.addEventListener(type, fn, false); }}
该函数首先检查attachEvent和addEventListener属性,谁可以就用谁,这两种类型的模型都支持删除句柄功能,参考下面的removeEvent函数。
function removeEvent(elem, type, fn) { if (elem.detachEvent) { elem.detachEvent(‘on‘ + type, fn); return; } if (elem.removeEventListener) { elem.removeEventListener(type, fn, false); }}
你可以这样使用:
var myIntro = document.getElementById(‘intro‘);addEvent(myIntro, ‘click‘, function () { alert(‘YOU CLICKED ME!!!‘);});
注意到我们传入了一个匿名函数作为第三个参数,JavaScript运行我们定义和执行匿名函数,这种匿名函数特别适合作为参数传递,实际上我们也可以传递有名的函数(代码如下),但是你们函数更容易做。
如果你只想在第一次click的时候触发一个函数,你可以这么做:
// 注意:前提是我们已经定于好了addEvent/removeEvent函数// (定义好了才能使用哦) var myIntro = document.getElementById(‘intro‘);addEvent(myIntro, ‘click‘, oneClickOnly); function oneClickOnly() { alert(‘WOW!‘); removeEvent(myIntro, ‘click‘, oneClickOnly);}
当第一次触发以后,我们就立即删除该句柄,但是有匿名函数的话却很难将自身的引用删除,不过实际上可以通过如下的形式来做(只不过有点麻烦):
addEvent(myIntro, ‘click‘, function () { alert(‘WOW!‘); removeEvent(myIntro, ‘click‘, arguments.callee);});
这里我们是有了arguments对象的callee属性,arguments对象包含了所有传递进来的参数以及该函数自身(callee),这样我们就可以放心地删除自身的引用了。
Event对象
另外一个非常重要的内容是Event对象,当事件发生的时候出发某个函数,该Event对象将自动在函数内可用,该对象包含了很多事件触发时候的信 息,但IE却没有这么实现,而是自己实现的,IE浏览器是通过全局对象window下的event属性来包含这些信息,虽然不是大问题,但我们也需要注意 一下,下面的代码是兼容性的:
function myEventHandler(e) { // 注意参数e // 该函数调用的时候e是event对象(W3C实现) // 兼容IE的代码 e = e || window.event; // 现在e就可以兼容各种浏览器了 } // 这里可以自由地绑定事件了
这里判断e对象(Event对象)是否存在我们使用了OR操作符:如果e不存在(为null, undefined,0等)的时候,将window.event赋值给e,否则的话继续使用e。通过这方式很快就能在多浏览器里得到真正的Event对象,如果你不喜欢这种方式的话,你可以使用if语句来处理:
if (!e) { e = window.event;} // 没有else语句,因为e在其它浏览器已经定义了
另外Event对象下的命令和属性都很有用,遗憾的是不不能全兼容浏览器,例如当你想取消默认的行为的时候你可以使用Event对象里的preventDefault()方法,但IE里不得不使用对象的returnValue属性值来控制,兼容代码如下:
function myEventHandler(e) { e = e || window.event; // 防止默认行为 if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; }}
例如,当你点击一个连接的时候,默认行为是导航到href里定义的地址,但有时候你想禁用这个默认行为,通过returnValue和preventDefault就可以实现,Event对象里的很多属性在浏览器里都不兼容,所以很多时候需要处理这些兼容性代码。
注意:现在很多JS类库都已经封装好了e.preventDefault代码,也就是说在IE里可用了,但是原理上依然是使用returnValue来实现的。