怎样正确注册事件和手动触发事件

记得那会刚学JavaScript的时候,注册事件都喜欢用最原始的方式(以下说的IE,都为早版本的IE,比如6,7,8)

<input type="button" id="btn" value="点我" />
var btn=document.getElementById("btn");
btn.onclick=function(){
    alert("点击了btn");
}

这样的确是没有问题,所有浏览器都支持。但是,有一点不好的是,多人开发的时候,别人也可能这样给btn注册了一个click事件,然后我在这样注册一个click事件,别人注册的事件就被我的给覆盖了。看人家jQuery,不论注册多少个事件,都会执行。那他是怎么实现的呢

if (window.addEventListener) {
    //标准事件模型
    btn.addEventListener("click", function () { alert("标准事件模型 点击 btn"); }, false);
    btn.addEventListener("click", function () { alert("标准事件模型 点击 btn2次"); }, false);
} else {
    //IE事件模型
    btn.attachEvent("onclick", function () { alert("IE事件模型 点击 btn"); });
    btn.attachEvent("onclick", function () { alert("IE事件模型 点击 btn2次"); });
}

看我给btn注册了两个事件,事件会依次执行(IE里会反过来,后注册的先执行)。标准事件模型最后一个参数代表是否在事件捕获阶段触发执行函数,为了兼容IE,一般都传false,因为IE不支持事件捕获,只支持事件冒泡。

如果要想把注册的事件删除呢,其实删除是可以的,只是上面的监听方法是匿名的,连个名字都没有,所以,这里就删不了

var fnClick=function(){alert("点击 btn");};
if (window.addEventListener) {
    //标准事件模型
    btn.addEventListener("click", fnClick, false);
    btn.removeEventListener("click", fnClick, false);
} else {
    //IE事件模型
    btn.attachEvent("onclick", fnClick );
    btn.detachEvent("onclick", fnClick );
}

这里,这个事件是不会执行的,因为事件注册之后就被删除了

有时候有这样的情况,在一个闭包里,给按钮注册了一个click事件,绑定处理函数A,且假定A为私有的。在另一个闭包里,我想执行那个函数A,但是访问不到,怎么办呢。

事件虽然是私有的,但是按钮是全局且公共的呀,可以手动触发按钮的click事件嘛,这样,就能间接执行函数A了

if (window.addEventListener) {
    //标准事件模型
    btn.addEventListener("click", function () { alert("标准事件模型 点击 btn"); }, false);
    //创建一个事件对象,只能用给定的字符串创建,比如 HTMLEvents MouseEvents UIEvents
    var evObj = document.createEvent('MouseEvents');
    //初始化事件对象,initEvent只是一个通用的初始化方法,这里还可以用别的初始化方法,比如initMouseEvent,但是这个方法参数太多,我们选用通用方法
    evObj.initEvent('click', true, false);  //第二个参数,代表事件是否应该冒泡,第三个参数代表事件是否可以被取消
    btn.dispatchEvent(evObj);               //触发事件
} else {
    //IE事件模型
    btn.attachEvent("onclick", function () { alert("IE事件模型 点击 btn"); });
    btn.fireEvent('onclick');               //IE里,很简单,直接调用 fireEvent 触发事件
}

当然,初始化事件的方法,还有 initMutationEvent,initKeyboardEvent,感兴趣的可以去了解一下。其实事件模型很复杂,我也在学习中,DOM0、DOM1、DOM2、DOM3里的模型都会有出入,期望赶快更新换代吧,痛苦的前端程序猿