您的位置:首页 > Web前端 > JavaScript

JavaScript中的事件:事件处理程序

2012-12-19 11:12 597 查看
最近在看《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中的作用域问题。但用来添加和移除事件处理程序还是足够的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: