[关闭]
@panhonhang 2018-06-08T18:10:35.000000Z 字数 5105 阅读 480

事件处理程序(HTML,DOM0,DOM2,IE)

未分类


HTML事件处理程序:

    <script type="text/javascript">
            function showMessage() {
                alert('message');
            }
    </script>
    <input type="text" name="username"  >
        <input type="text" name="username"  onclick="alert(this.value)">
        <input type="text" name="username"  onclick="alert(value)">
        <input type="button" value="click me" onclick="showMessage()">

最后一个点击事件,假设showMessage()函数实在按钮下方,页面最底部进行定义。如果用户在页面解析showMessage()函数之前就单击了按钮,就会引发错误。为此,很多HTML事件处理程序都会被封装到try-catch块中,以便错误不会浮出水面,如下面的例子所示:

<input type="button" value="click me" onclick="try(showMessage();)catch(ex){}">

这样,如果在showMessage()函数有了定义之前单击了按钮,用户将不会看到JavaScript错误,因为在浏览器有机会处理错误之前,错误就被捕获了。

note:

(1)通过event变量可以直接访问事件本身,比如onclick=”alert(event.type)”会弹出click事件。

(2)this值等于事件的目标元素,这里目标元素是input。比如 onclick=”alert(this.value)”可以得到input元素的value值。

0级DOM事件处理程序
     JS写onlicke=function(){}函数

var oBtn = document.getElementById("myButton");
oBtn.onclick = function () {
alert('thanks');
};

DOM2级事件处理程序
DOM2级事件定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()、removeEventListener()。所有的DOM节点都包含这两个方法,并且接受三个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
要在按钮上添加click事件处理程序,可以使用下面的代码

var oBtn = document.getElementById("btn1");
oBtn.addEventListener('click',function(){
alert(this.value);
},false);

因为第三个参数是false,所以它会在冒泡阶段被触发。
使用DOM2级方法添加事件处理程序的好处是可以添加多个事件处理程序。看下面的例子:

var oBtn = document.getElementById("btn1");
oBtn.addEventListener('click',function(){
    alert(this.value);
},false);
oBtn.addEventListener('click',function(){
    alert(this.id);
},false);

这里为按钮添加了两个事件处理程序,这两个事件处理程序会按照添加的顺序出发,因此会获得button的value,在获得其id。
如果第三个参数为true,那么看如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript">
        window.onload = function() {

            var oBtn = document.getElementById("btn1");
            oBtn.addEventListener('click',function(){
                alert('button click');
            },true);

            var oBD = document.getElementsByTagName('body')[0];
            oBD.addEventListener('click',function(){
                alert('body click');
            },true);
        }
    </script>
</head>
<body>
    <input type="button" value="click me" id="btn1">
</body>
</html>

那么先弹出‘button click’,后弹出“body click”。
那么这里解释一下:
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的事件捕获,为截取事件提供了机会。然后是实际的目标接收事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。看下图:
哈哈哈,有点丑
很显然事件捕获阶段是从不具体节点(文档)到目标点的,所以当第三个参数为true是,在捕获阶段就调用了事件处理程序。
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序是使用的参数相同。这也意味着通过addEventListener()添加的匿名函数无法移除,如下面的例子所示:

var oBtn = document.getElementById("btn1");
oBtn.addEventListener('click',function(){
    alert(this.value);
},false);
oBtn.removeEventListener('click',function(){
    alert(this.value);
},false);

看着参数一样,但实际上,第二个参数与传入addEventListener()中的那一个是完全不同的函数。而传入removeEventListener()中的事件处理程序函数必须与传入addEventListener()中的相同,如下面的例子所示:

function doSomething() {
    alert('hello');
}
var oBtn = document.getElementById("div1");
oBtn.addEventListener('click',doSomething,false);
oBtn.removeEventListener('click',doSomething,false);

这个例子没有问题,因为在addEventListener()和removeEventListener()中使用了相同的函数

IE事件处理程序
IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE8只支持事件冒泡,所以通过attachEvent()添加的时间处理程序都会被添加到冒泡阶段。

<input id="myBtn" type="button" value="click me!"/>
<script>
    var myBtn=document.getElementById("myBtn");
    var handlerIE=function(){
        alert("helloIE");
    }
    var handlerDOM= function () {
        alert("helloDOM");
    }
    myBtn.addEventListener("click",handlerDOM,false);
    myBtn.attachEvent("onclick",handlerIE);
</script>

note:
attachEvent的第一个参数是onclick,而不是addEventListener的click

IE11只支持addEventListener!

IE9,IE10对attachEvent和addEventListener都支持!

TE8及以下版本只支持attachEvent!

删除事件处理程序:通过attachEvent添加的事件处理程序必须通过detachEvent方法删除,且参数一致。

和DOM事件一样,添加的匿名函数将无法删除。

所以为了能删除事件处理程序,代码可以这样写

<input id="myBtn" type="button" value="click me!"/>
<script>
    var myBtn=document.getElementById("myBtn");
    var handler= function () {
        alert("hello");
    }
    myBtn.attachEvent("onclick",handler);
    myBtn.detachEvent("onclick",handler);
</script>

note:IE事件处理程序中还有一个地方需要注意:作用域。

使用attachEvent()方法,事件处理程序会在全局作用域中运行,因此this等于window。
而dom2或dom0级的方法作用域都是在元素内部,this值为目标元素。
下面例子会弹出true。

<input id="myBtn" type="button" value="click me!"/>
<script>
    var myBtn=document.getElementById("myBtn");
    myBtn.attachEvent("onclick",function(){
        alert(this===window);
    });
</script>

跨浏览器的事件处理程序
要保证处理时间的代码能在大多数浏览器下一致运行,只需要关注冒泡阶段。
第一个要创建的方法是addHandler(),他的职责是视情况分别使用DOM0级方法,DOM2级方法或IE方法来添加事件。这个方法的属于一个名叫EventUtil的对象,addHandler()方法接受三个参数:要操作的元素,事件名称和事件处理程序函数。
与addHandler()对应的方法是removeHandler(),他也接受相同的参数。这个方法的职责是移除之前添加的事件处理程序——无论该事件处理程序是采取什么方式添加到元素中的,如果其他方法无效,默认采用DOM0级方法。
EventUtil的用法如下:

<script type="text/javascript">
        var EventUtil = {
            addHandler:function (element,type,handler) {
                if (element.addEventListener) {
                    element.addEventListener(type,handler,false);
                }else if (element.atachEvent) {
                    element.atachEvent('on'+type,handler);
                }else {
                    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);
                }element {
                    element['on'+type] = null;
                }
            }
        }
    </script>

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

var oBtn = document.getElementById("btn1");
var handler = function () {
    alert('clicked');
}
EventUtil.addHandler(oBtn,'click',handler);
EventUtil.removeHandler(oBtn,'click',handler);

addHandler和removeHandler没有考虑到所有的浏览器问题,例如IE中的作用于问题。但是使用EventUtil进行添加和移除事件已经足够了。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注