资讯专栏INFORMATION COLUMN

前端基础 - 事件入门

bbbbbb / 1704人阅读

摘要:及更早版本不支持事件流。绑定作用域其他的地方,就跟类似,都可以绑定多个事件处理程序,要删除只能调用,并且不能使用匿名函数的形式。

事件知识快速入门

事件是前端开发必备的知识,我通过阅读《JavaScript高级程序设计》,梳理了一下整个事件的知识体系,下面一起来学习吧。

1. 背景知识

跟所有开发UI的思路一样,JavaScript与HTML之间通过事件来进行交互。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间,我们使用监听器(listener/hanlder)来预订事件,当事件触发时,执行相对应的代码,这种就是传统软件工程中被成为观察者模式的模型,这种模型支持页面的行为与页面的UI之间的松散耦合。

2. 事件流

理解事件流,我们可以从一个问题出发,那就是:页面的哪一个部分会拥有某个特定的事件?当我们点击了一个button时,点击事件不仅发生在按钮上,换句话说,在单击按钮的同时,也是单击了按钮的容器元素,甚至也单击了整个页面。

这便有了事件流的概念,它描述的就是从页面中接收事件的顺序。而事件流有两种:

事件冒泡

事件捕获

早期,IE和Netscape的事件流顺序是相反的,IE是事件冒泡流,Netscape是事件捕获流

2.1 事件冒泡

IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点。

例如:



    
        Event Bubbling
    
    
        
click

当我们点击页面中的div元素时,这个click事件会按照如下的顺序传播

IE9、firefox、chrome和safari会将事件一直冒泡到window对象。

2.2 事件捕获

NetScape提出的另一种事件流叫做事件捕获,即是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件,它的用意在于事件到达预定目的之前捕获它。

还是以上面的html代码为例子,则当我们点击页面的div元素时,这个click事件的顺序为:

2.3 DOM 事件流

DOM2级事件规定事件流包括三个阶段:

事件捕获阶段,为截获事件提供了机会

处于目标阶段,实际的目标接收到事件

事件冒泡阶段,也可以在这个阶段对事件作出响应

需要注意的有两点:

尽管DOM2级事件规范要求事件应该从document对象开始传播,但是大多数浏览器都是从window对象开始捕获的。

DOM2级明确要求捕获阶段不会涉及事件目标,但是IE9,safari,chrome,firefox和opera9.5都会在捕获阶段触发事件对象上的事件,结果,就是有两个机会在目标对象上操作事件。

IE8及更早版本不支持DOM事件流。

3. 事件处理程序

事件是用户或浏览器自身执行的某种动作,而响应某个事件的函数就叫做事件处理程序。

设置事件处理程序的方式有4种,以下来一一介绍。

3.1 HTML事件处理程序

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

我们可以直接在属性中的js代码中通过event变量获取到event对象,代码中的this指的是事件的目标元素。

这种方式在很多古老的页面中都可以看到,它比较的简单,粗暴。但是它导致了HTML与JavaScript代码紧密耦合,从实践的角度上,最好不要采用这样的形式。

3.2 DOM0级事件处理程序

通过JavaScript指定的事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。

这个方式有两个优点:

简单

跨浏览器,至今所有的现代浏览器都支持。

var btn = document.getElementById("btn");
btn.onclick = function (event) {
    alert(event.type);
    alert(this.id);
}

需要注意的是,通过这个方式进行设置,我们无法对同一个元素的同一个事件绑定多个事件处理程序(会覆盖),例如以下代码,就只会执行最后设置的函数。

var btn = document.getElementById("btn");
btn.onclick = function (event) { // 不会执行
    alert(event.type);
    alert(this.id);
}
btn.onclick = function (event) { 
    alert("覆盖了");
}

依据这个特性,我们可以通过btn.onclick = null来删除设置的事件处理程序。当然我们也可以通过以下的技巧,来为其绑定多个事件处理程序。

var btn = document.getElementById("btn");
btn.onclick = function (event) { 
    alert(event.type);
    alert(this.id);
}

var oldHandler = btn.onclick; // 获取前面设置的事件处理程序

btn.onclick = function (event) { 
    oldHandler.call(this, event);
    alert("覆盖了");
}
3.3 DOM2级事件处理程序

DOM2级事件定义了两个方法,用于处理指定和删除事件程序的操作

addEventListener(type, listener, isCapture)

removeEventListener(type, listener, isCapture)

它们接收三个参数:

要处理的事件名(不需要带on,例如点击事件是click

作为事件处理程序的函数

布尔值,为true时表示捕获阶段调用事件处理程序,为false则表示冒泡阶段调用事件处理程序

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

使用这个方式的主要好处就是可以添加多个事件处理程序

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

通过addEventListener方式添加的事件处理程序只能通过removeEventListener来删除,这就是说如果我们采用匿名函数的方式来添加事件处理程序的话,则无法进行删除,因此比较好的方式就是:

var btn = document.getElementById("btn");

function handler(event) {
    alert(event.type);
    alert(this.id);
}

btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);

在大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。

3.4 IE事件处理程序

IE实现了与DOM中类似的两个方法:

attachEvent(type, listener)

detachEvent(type, listener)

参数type是on+事件名,如点击事件,则是onclick

由于IE8及更早版本只支持事件冒泡,所以通过attachEvent()添加事件处理程序都会被添加到冒泡阶段。



    
        Event Bubbling
    
    
        
        
    

上面的代码其实是有问题的,当alert(this.id)时,会看到结果为undefined,这就是使用这个方法特别要注意的地方,事件处理程序会在全局作用域中运行,因此this等于window。

我们可以运用一个小技巧,来修复这个问题。

var btn = document.getElementById("btn");

function handler(event) {
    alert(event.type);
    alert(this.id);
}

btn.attachEvent("onclick", function (event){
    handler.call(btn, event); // 绑定作用域
});

其他的地方,attachEvent()就跟addEventListener()类似,都可以绑定多个事件处理程序,要删除只能调用detachEvent(),并且不能使用匿名函数的形式。

支持IE事件处理程序的浏览器有IE和Opera

4. 总结

掌握了这些知识之后,我们就可以动手去编写我们的跨浏览器的事件处理程序了^_^

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90963.html

相关文章

  • 【连载】前端个人文章整理-从基础入门

    摘要:个人前端文章整理从最开始萌生写文章的想法,到着手开始写,再到现在已经一年的时间了,由于工作比较忙,更新缓慢,后面还是会继更新,现将已经写好的文章整理一个目录,方便更多的小伙伴去学习。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 个人前端文章整理 从最开始萌生写文章的想法,到着手...

    madthumb 评论0 收藏0
  • 前端基础入门六(JQuery进阶)

    摘要:获取元素距离的位置返回值为对象获取相对于其最近的有定位的父元素的位置。不仅提供了更加优雅的事件处理语法,而且极大的增强了事件的处理能力。注册简单事件表示给绑定事件,并且由自己触发,不支持动态绑定。 jQuery特殊属性操作 val方法 val方法用于设置和获取表单元素的值,例如input、textarea的值 //设置值 $(#name).val(张三); //获取值 $(#name)...

    fnngj 评论0 收藏0
  • 前端培训-中级阶段(6)- jQuery的事件绑定链式操作及原理(2019-07-25期)

    摘要:前端最基础的就是。帮助从旧的事件方法转换,和。方法移除用绑定的事件处理程序。特定的事件处理程序可以被移除元素上提供事件名称,命名空间,处理函数。用于过滤器的触发事件的选择器元素的后代。事件触发模拟触发原生使用触发。 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS)...

    Airy 评论0 收藏0
  • 前端培训-中级阶段(6)- jQuery的事件绑定链式操作及原理(2019-07-25期)

    摘要:前端最基础的就是。帮助从旧的事件方法转换,和。方法移除用绑定的事件处理程序。特定的事件处理程序可以被移除元素上提供事件名称,命名空间,处理函数。用于过滤器的触发事件的选择器元素的后代。事件触发模拟触发原生使用触发。 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS)...

    sutaking 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<