深刻理解js Dom事件机制(二)——添加事件处理程序

  1. 深刻理解js Dom事件机制(一)——事件流
事件就是当用户或者浏览器自身执行的某种动做,诸如 click、mouseover等都是事件的名称,那响应个事件的函数就称为事件处理程序(事件处理函数、事件句柄)。 事件处理程序的名字都是以on+事件名称命名,好比 click事件的事件处理程序就是onclick, 为某个事件指定事件处理程序的方式大体分为三种。

一、HTML事件处理程序

这个很简单,你们基本初学js的时候都应该用过,就再也不赘述,直接看实例代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Html事件处理程序</title>
</head>
<body>
    <!-- 第一种:直接在html中定义事件处理程序和事件动做 -->
    <input type="button" value="clcik me" onclick="console.log(event.type, this.value);"> <!-- click click me -->
    <!-- 第二种:html中定义事件处理程序,执行的动做则调用其余地方的脚本 -->
    <input type="button" value="happy" onclick="happy()">
</body>
<script type="text/javascript">
    function happy() {
        console.log(this === window);
        // true
    }
</script>
</html>
以上代码展现了两种html指定事件处理程序的方法,须要注意的是 第一种作法的this指向的是元素自己, 因此咱们能够很容易的访问元素自己的属性,而第二种作法的this指向的window对象。
缺点:
  1. 存在时差问题,当用户在元素出如今页面就触发事件,但有可能这个时候事件处理程序不具有执行的条件。
  2. html与js代码耦合度高,这正是不少开发者放弃html事件处理程序的缘由。

二、DOM0级事件处理程序

这种方式首先须要取得一个dom元素对象的应用,而后将一个函数赋值给一个事件处理程序,这种方式在第四代浏览器中就已经出现,至今仍然为如今浏览器所支持,缘由一是简单,二是具备跨浏览器的优点。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>DOMO级事件处理程序</title>
</head>
<body>

    <input type="button" value="happy" id="happy">
</body>
<script type="text/javascript">
    var btn = document.getElementById('happy');
    btn.onclick = function () {
        console.log(this.value); // happy
    }
</script>
</html>
经过上面的代码能够看出,这种方法指定的事件处理程序中this是指向元素自己。相对应的这种方法也能够删除指定的事件处理程序: btn.onclick = null.

三、DOM2级事件处理程序

DOM2级事件定义了两个方法,用于处理指定和删除事件处理程序的操做:addEventListener()、removeEventListener(),它们都接受三个参数:要处理的事件名、事件处理函数、布尔值(true:在捕获阶段调用事件处理函数,false:在冒泡阶段调用事件处理函数)。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>DOM2级事件处理程序</title>
</head>
<body>

    <input type="button" value="happy" id="happy">
</body>
<script type="text/javascript">
    var btn = document.getElementById('happy');
    btn.addEventListener('click',function happy() {
        console.log('事件捕获阶段被单击')
    },true)
    btn.addEventListener('click',function happy() {
        console.log('事件冒泡阶段被单击')
    },false)
    btn.addEventListener('mouseover',function happy() {
        console.log('鼠标移入啦')
    })
</script>
</html>
从上述代码中能够看出:
  1. addEventListener能够对一个元素添加多个事件处理程序,并能够声明是将事件处理程序添加到哪个阶段(为了保证兼容性、建议都将事件处理程序添加到冒泡阶段)。
  2. 须要特别注意的是:removeEventListener移除事件处理函数的时候,传入的事件事件处理函数必须和addEventListener传入的相同,方可移除,这就意味着若是addEventListener中使用了一个匿名函数来做为事件处理函数,那么removeEventListener将没法移除。

四、IE事件处理程序(IE8 && IE8 - && Opera)

IE实现了相似DOM中的两个方法:attacheEvent()、detachEvent(),它们接受两个参数:事件处理程序名称、事件处理函数。因为IE8以及更早的浏览器只支持冒泡事件流,因此经过attacheEvent()添加的事件处理程序都将在会被添加到冒泡阶段。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>IE事件处理程序</title>
</head>
<body>

    <input type="button" value="happy" id="happy">
</body>
<script type="text/javascript">
    var btn = document.getElementById('happy');
    btn.attachEvent('click',function happy() {
        console.log('事件冒泡阶段被单击')
    })
    btn.attachEvent('mouseover',function happy() {
        console.log('鼠标移入啦')
    })
</script>
</html>

与DOM2级方法的异同javascript

  • 相同:html

    一、均可以添加和移除事件处理程序,匿名函数均不可移除。
       二、均可以添加多个事件处理程序。
  • 不一样:java

    一、IE的事件处理函数会在全局做用于执行,因此this指向window,而DOM方法中this指向元素对象引用
       二、当添加多个事件处理程序时:执行的顺序和DOM2级事件处理程序相反。

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

为了保证事件处理的代码能在大部分的浏览器下获得一致性的运行,咱们能够恰当的使用浏览器能力检测能力封装一个通用的事件处理程序添加函数。
let eventUtil = {
    addEventHandle(element, eventType, handle) {
        if (Object.prototype.toString.apply(handle) !== '[object Function]') {
            throw new TypeError('handle invaild')
        }
        if (!element.addEventListener) {
            element.addEventListener(eventType,handle)
        } else if (element.attachEvent) {
            element.attachEvent(`on${eventType}`,handle)
        } else{
            element[`on${eventType}`] = handle
        }

    },
    removeEventHandle(element, eventType, handle) {
        if (Object.prototype.toString.apply(handle) !== '[object Function]') {
            throw new TypeError('handle invaild')
        }
        if (!element.removeEventListener) {
            element.removeEventListener(eventType,handle)
        } else if (element.detachEvent) {
            element.detachEvent(`on${eventType}`,handle)
        } else{
            element[`on${eventType}`] = null
        }

    }
}
上面的代码很简单,首先判断浏览器是否支持addEventHandle, 若是支持就用它来添加事件程序,不然再判断attachEvent,若是还不支持只能用Dom0级事件添加, 可是针对IE8--使用attachEvent添加事件处理程序时,this的指向并无作处理,包括事件触发的阶段等。
相关文章
相关标签/搜索