最近在看《JavaScript高级程序设计》(第3版),一直没有记录的习惯。现在把一些东西记下来,加深下印象。(基本是照着书码出来的- -!)

一、HTML事件处理程序

某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的JS代码。如,

 <input type="button" value="Click Me" onclick="alert('Clicked')" />

由于这个值是JS代码,因此不能在其中使用未经转义的HTML语法字符。如& "" < >。

在HTML中定义的事件处理程序也可以调用在页面其他地方定义的脚本。如,

 <script type="text/javascript">
     function showMsg(){
         //代码
     }
 </script>
 <input type="button" value="Click Me" onclick="showMsg()" />

HTML事件处理程序会创建一个封装着元素属性值的函数,这个函数中有一个局部变量event,即事件本身,不必定义它,也不用从函数参数列表中读取。如,

 <input type="button" value="Click Me" onclick="alert(event.type)" />

在函数内部,this值等于事件的目标元素,如

 <input type="button" value="Click Me" onclick="alert(this.value)" />

在HTML中指定事件处理程序主要有三个缺点:

1. 存在时差问题。用户可能会在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。若前面的showMsg()函数是在按钮下方、页面的最底部定义的 ,如果用户在页面解析该函数前就单击了按钮,就会引发错误。为此,可以使用try-catch块。如,

 <input type="button" value="Click Me" onclick="try{showMsg();}catch(ex){}" />

2. 这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。不同JS引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。

3. HTML与JS代码紧密耦合,不便于维护。这应该是主要的缺点了,几乎没人愿意用这方法了吧。

二、DOM0级事件处理程序

通过JS指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。至今仍被所有现代浏览器支持。简单,且具有跨浏览器优势。

首先应取得一个要操作的对象的引用。如,

 var btn=document.getElementById("myBtn");
 btn.onclick=function(){
    //代码         
 };

注意如果以上代码在页面中位于按钮后面,有可能在一段时间内怎么单击都没反应这里是指,比如文档要载入的文件很多,而以上代码放在按钮后面,在执行到这些代码之前,该按钮是不会绑定该事件的,即怎么单击都没反应。在这里有一点要注意的是,要取得一个对象的引用,必须在该对象被解析之后。看以下代码:

<head>
<script type="text/javascript>
var btn=document.getElementById("myBtn");
btn.onclick=function(){
    //代码         
};
</script>
</head>
<body>
<input type="button" id="myBtn" value="Click Me" />
</body>

单击按钮并没有任何反应。这是因为var btn=document.getElementById("myBtn");并没有取得对象的引用,此时<body>里面的<input>还未被解析。这时要利用window.onload:

<head>
<script type="text/javascript">
window.onload=function(){
    //包含上面的JS代码
}
</script>
</head>

 window.onload在文档所有元素加载完后执行,这样便能取得对象的引用。当然,将<script>标签放在后面也可以,如,

<body>
<input type="button" id="myBtn" value="Click Me" />
<script type="text/javascript>
var btn=document.getElementById("myBtn");
btn.onclick=function(){
  //代码
};
</script> </body>

结果跟用window.onload一样。

通过DOM0级添加的事件处理程序被认为是元素的方法,即函数内的this引用当前元素,可以通过this访问元素的任何属性和方法。而要删除事件处理程序,则可以如下这样(在HTML指定的事件也如此),

 btn.onclick=null;

三、DOM2级事件处理程序

DOM2级事件定义了两个方法:addEventListener()和removeEventListener()。所以DOM节点都包含这俩方法,它们接受3个参数,见代码如下,

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
  alert(this.id);
},false
);

最后的参数false表示在冒泡阶段调用该程序。

使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。如,

 var btn=document.getElementById("myBtn");
 btn.addEventListener("click",function(){
     alert(this.id);
     },false
 );
 btn.addEventListener("click",function(){
     alert("hello world");
     },false
 ); 

这两个事件处理程序会按照添加它们的顺序触发。

通过addEventListener()添加的事件处理程序只能通过removeEventListener()来移除,且参数要相同,意味着添加的匿名函数无法移除。可以用下面的方法,

var btn=document.getElementById("myBtn");
var handler=function(){
     //代码
};
btn.addEventListener("click",handler,false);
btn.addEventListener("click",handler,false);      

IE9、FF、Safari、Chrome和Opera支持DOM2级事件处理程序。

四、IE事件处理程序

IE实现了与DOM类似的两个方法:attachEvent()和detachEvent()。由前者添加的事件只能由后者来移除,且参数要相同,同样添加的匿名函数无法移除,具体方法见上面代码。

attachEvent()与addEventListener()一样,可以为一个元素添加多个事件,不同的是attachEvent()添加的事件是以相反的顺序被触发的。要注意的是,IE8及更早版本只支持事件冒泡,没有第三个参数。且参数中的事件处理程序名称有前缀on-,与DOM2级不同,如下,

 var btn=document.getElementById("myBtn");
 btn.attachEvent("onclick",function(){
     //代码
 });

在IE中使用attachEvent()与使用DOM方法的主要区别在于事件处理程序的作用域。在DOM方法下,事件处理程序会在其所属元素的作用域中运行;而使用attachEvent(),则会在全局作用域中运行,即this等于window。编写跨浏览器代码时,牢记这一点很重要。

 五、跨浏览器的事件处理程序

var EventUtil={
    addHandler:function(element,type,handler)
if(element.addEventListener){ //检测是否存在DOM2级方法                element.addEventListener(type,handler,false); } else if(element.attachEvent){ //IE中的方法 element.attachEvent("on"+type,handler); } else{ //DOM0级方法 element["on"+type]=handler; } }, removeHandler:function(element,type,handler){ if(element.removeEventListener){ element.removeEventListener(type,handler,false); } else if(element.detachEvent){ element.detachEvent("on"+type,handler); } else{ element["on"+type]=null; } } };

可以像下面这样使用EventUtil对象:

var btn=document.getElementById("myBtn");
var handler=function(){
    //代码
};
EventUtil.addHandler(btn,"click",handler);
EventUtil.removeHandler(btn,"click",handler);

以上没有考虑所有的浏览器问题,如在IE中的作用域问题。但用来添加和移除事件处理程序还是足够的。

posted on 2012-12-19 11:12  no_particular  阅读(701)  评论(2编辑  收藏  举报