很全面的JavaScript事件讲解

130 阅读5分钟

前言

之前在b站和一些教程上看过一次有关事件的讲解,但是越看越迷惑,我在开发中有蛮多疑惑的点,虽说是开发经验不够多,但是我觉得对于事件这模块,我们还是没有深入进去,我只是了解事件的冒泡和事件的捕获,对于事件也就仅此而已,所以我打算深入学习一下,文章还不成熟,希望大家能给好的意见。

定义

对于事件,我的理解是元素本身的一个属性,它从一开始就有的属性,哪怕我们不去指定,它也是存在的,而我们指定的仅仅就是事件的处理函数,仅仅就是当我们触发元素本身的事件时才会做出的一个反应。而事件+事件的反馈就是前端交互。

事件句柄

事件句柄在W3C上面所说是通过一个事件句柄,您可以在某个事件发生时对某个元素进行某种操作:当用户点击元素时,当页面加载时,当一个表单被提交时,等等。

按照W3C所说,句柄是我们指定事件处理函数。但是我仔细看了下所有的事件句柄,发现是以on开头的一些事件处理函数,没有我们所知道的事件注册如addEventListener.所以事件句柄是DOM0时的规范,而事件句柄默认时按照事件冒泡来执行的

事件绑定

我们在绑定事件处理函数的时候有三种写法

<!-- 第一种通过标签的属性如onclick -->
<div onclick=""></div>
// 第二种就是通过Dom对象指定onlick属性,给它赋值一个函数
<div></div>

var oDiv = document.getElementsByTagName()[0];
oDiv.onClick = function () {}

// 第三种就是用事件注册的方式
odiv.addEventListener(事件类型,事件处理函数,是否开启事件捕获)

看起来有很多方法能指定事件的处理函数,但是这三种区别的。首先就是onClick只能指定一个onClick事件的,事件句柄不支持指定多个相同类型的事件函数,而addEventListener是可以指定多个同类型的事件处理函数的,但是如果你的第二个参数指定的函数是同个函数的话是会报错的,而且在IE9以下的浏览器是不支持addEventListener这个函数的。如果是要兼容IE9以下的浏览器的话,得使用Dom元素下面的一个方法attachEvent,这个函数的参数和那个addEventListener很相似,唯一不同的是没有指定是否开启事件捕获。但是需要注意的是使用这个函数的时候得给它传递this,不然这个this指向的是那个window对象.

事件解除

事件解除有两种方式进行解除

// 第一种就是给onClick赋值一个null,利用浏览器回收机制删除
<div></div>

var oDiv = document.getElementsByTagName()[0];
oDiv.onClick = function () {}

// 第二种就是用事件注册的方式
odiv.removeEventListener(事件类型,事件处理函数,是否开启事件捕获)
// IE9以下兼容方法,但是得注意this指向
odiv.detachEvenet(事件类型,事件处理函数)

事件流

事件流包括事件冒泡、处于目标、事件捕获。而网景公司认为事件流是事件冒泡,但是W3C认为事件流是事件捕获.但是如果是处于目标中的话是按照代码编写顺序来执行的,一般事件捕获是优先于事件冒泡的。

事件冒泡

事件冒泡就是类似冒泡一样,当触发源目标的事件时,先执行自身的事件处理函数,再将事件传递给上级元素,上级元素判断自身是否有同类型的事件处理函数,如果有就执行事件处理函数,如果没有就往上面传递。直到最顶的元素。

事件冒泡虽然看起来没啥用处,但是在一些业务场景还是很有作用的。例如在购物商城的分类选项的时候,如果一个个绑定点击事件的话,得绑定很多事件点击,如果是使用事件冒泡的话只要给父级元素绑定一个事件处理函数就好了。然后我们通过event对象下面的target这个属性来点击的事件源。这个就是事件代理。

但是在IE8event对象是储存在window身上的,而不是储存在事件处理函数的参数上。然后target这个属性在IE浏览器是没有的,只有srcElement这个属性

但是事件冒泡有时候也是不好的,得解除

阻止事件冒泡

IE8是使用的是event对象下面的cancelBubble属性为true来组织的,在W3C中是通过event.stopPropagation()方法。

事件捕获

事件捕获和事件冒泡刚好是相反的,首先事件源被触发时,先去最上层元素找是否有同类型的事件处理函数,如果有就调用,没有就往下传递。最后在事件源上触发事件处理函数。

Focus、blur、change、submit、reset、elect 和IE9是没有事件捕获

取消默认事件

一般我们取消默认事件是取消a标签的跳转,我们可以通过event.preventDefault()来取消,但是IE9不兼容,IE9以下得通过document.oncontextmenu返回false和event.returnvalue为false