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

文章转载自https://segmentfault.com/a/1190000012022432

深入理解js Dom事件机制(一)——事件流

事件就是当用户或者浏览器自身执行的某种动作,诸如 click、mouseover等都是事件的名称,那响应个事件的函数就称为事件处理程序(事件处理函数、事件句柄)。 事件处理程序的名字都是以on+事件名称命名,比如 click事件的事件处理程序就是onclick, 为某个事件指定事件处理程序的方式大致分为五种。

1. 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对象。
缺点:

  • 存在时差问题,当用户在元素出现在页面就触发事件,但有可能这个时候事件处理程序不具备执行的条件。
  • html与js代码耦合度高,这正是很多开发者放弃html事件处理程序的原因。

2. 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

3. 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>
</script>
</html>

从上述代码中可以看出:
addEventListener可以对一个元素添加多个事件处理程序,并可以声明是将事件处理程序添加到哪一个阶段(为了保证兼容性、建议都将事件处理程序添加到冒泡阶段)。

需要特别注意的是:removeEventListener移除事件处理函数的时候,传入的事件事件处理函数必须和addEventListener传入的相同,方可移除,这就意味着如果addEventListener中使用了一个匿名函数来作为事件处理函数,那么removeEventListener将无法移除。

详解可见 https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener

4. 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级方法的异同

  • 相同:
    1、都可以添加和移除事件处理程序,匿名函数均不可移除。
    2、都可以添加多个事件处理程序。
  • 不同:
    1、IE的事件处理函数会在全局作用于执行,所以this指向window,而DOM方法中this指向元素对象引用
    2、当添加多个事件处理程序时:执行的顺序和DOM2级事件处理程序相反。

5. 跨浏览器事件处理程序

为了保证事件处理的代码能在大部分的浏览器下得到一致性的运行,我们可以恰当的使用浏览器检测能力封装一个通用的事件处理程序添加函数。

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的指向并没有做处理,包括事件触发的阶段等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容

  •   JavaScript 与 HTML 之间的交互是通过事件实现的。   事件,就是文档或浏览器窗口中发生的一些特...
    霜天晓阅读 3,490评论 1 11
  • 事件流 JavaScript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互...
    DHFE阅读 828评论 0 3
  • 声明:本文来源于http://www.webzsky.com/?p=731我只是在这里作为自己的学习笔记整理一下(...
    angryyan阅读 7,010评论 1 6
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,126评论 0 21
  • 一、事件流 1.1 事件流 事件流:从页面中接受事件的顺序 事件冒泡:即事件开始时由最具体的元素(文档中嵌套层次最...
    范小饭_阅读 1,067评论 1 9