综合技术

深入理解javascript事件机制

微信扫一扫,分享到朋友圈

深入理解javascript事件机制
0

Created By JishuBao
on 2019-04-17 12:38:22

Recently revised in 2019-04-17 17:38:22

欢迎大家来到技术宝的掘金世界,您的star是我写文章最大的动力! GitHub地址

不知道各位小伙伴在平时撸码中会不会经常看到诸如 event.preventDefault()、event.stopPropagation()
之类的方法,可能一开始看到只是随便的百度了下,大概了解这是干嘛的,但是事件长了你只记得要点击事件的时候加上一下,但是这对于我们对代码的掌控还是远远不够,所以技术宝深刻百度,带大家理一理这个javascript大头: 事件机制

一、了解事件

什么是事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。js与html的交互就是通过事件实现的。可以使用 侦听器
(或处理程序)来预订事件,以便事件发生时执行相应的代码。

事件最早出现于 IE3
Netscape Navigator2
, IE9、Firefox、Opera、Safari、Chrome
全部已经实现 DOM2
事件. IE8
是最后一个仍然使用其专有事件系统的浏览器。

二、了解事件流

事件流描述的是从页面中接收事件的顺序。但是,IE和Netscape提出了差不多完全相反的概念。IE的事件流是事件冒泡流,而Netscape的事件流是事件捕获流。
虽然“dom2级事件”规范明确要求捕获阶段不会涉及到事件目标,但是IE9、Safari、Chrome、Safari及更高版本都会在捕获阶段触发事件对象上的事件。结果,就有2个机会在目标对象上操作事件。

IE9/Opera/Firefox/Chrome/Safari都支持DOM事件流;IE8以及更早版本 不支持
DOM事件流。

三、事件处理程序

事件就是用户或浏览器自身执行的某种动作。诸如click、load、mouseover,都是事件的名字。而相应某个事件的函数就叫做 事件处理程序(事件侦听器)
。事件处理程序以“on”开头,因此click的事件处理程序就是onclick。为事件指定处理程序的方式有好几种:

1.HTML事件处理程序

某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的Html特性来指定。这个特性的值应该是能够执行的js代码。

<input type="button" value="click me" onclick="alert('clicked')"/>
复制代码

由于值是js,所以不能使用未转义的HTML语法字符,如:&、""、>、<,为了避免使用HTML实体,这里使用了单引号。如果想使用双引号:

<input type="button" value="click me" onclick="alert("clicked me")" />
复制代码

除了包含具体的执行动作外,还可以调用其他地方定义的脚本(括号不可不加)

<input type="button" value="click me" onclick="showMessage()" />
<script type="text/javascript">
    function showMessage(){
        alert('Hello world')
    }
</script>
复制代码

事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码

这样指定事件处理程序会创建一个封装着元素属性值的函数。这个函数中有一个局部变量event,也就是 事件对象

<input type="button" value="click me" onclick="alert(event.type)"/>//click
复制代码

在这个函数内部,this的值等于事件的目标元素。

<input type="button" value="click me" onclick="alert(this.value)"/>//click me
复制代码

在这个函数内部,可以像访问局部变量一样访问document以及该元素本身的成员。这个函数使用with像下面这样扩展作用域:

function(){
    with(document){
        with(this){
            //元素属性值
        }
    }
}
复制代码

这样以来,访问自己的属性简单的多

<input type="button" value="click me 5" onclick="alert(type)"/>//button
复制代码

如果当前元素是一个表单输入元素,则:

function(){
    with(document){
        with(this.form){
            with(this){
                //元素属性值
            }
        }
    }
}
复制代码

则不需要引用表单元素就能访问其他表单字段

<form method="post">
	<input type="text" name="username" value="jsbao">
	<input type="button" value="Echo" onclick="alert(username.value)"> //jsbao
</form>
复制代码

这样存在3个缺点:

时差问题,用户可能会在html元素一出现就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。为避免不必要的错误,我们一般会用try-catch块包住:

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

扩展事件处理程序的作用域链在不同浏览器中会导致不同结果,因为不同Js引擎遵循的标识符解析规则略有差异!

html与js代码耦合度太高!

2.DOM0级事件处理程序

通过js指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。每个元素都是自己的事件处理程序属性,这些属性通常全部小写,例如onclick。将这种属性的值设置为一个函数,就可以指定事件处理程序。

<input type="button" value="click me 5" id="button1"/>
var button1=document.getElementById('button1')
button1.onclick=function(){
	alert('hello world')
}
复制代码

要注意,在这些代码运行之前不会指定事件处理程序,因此如果这些代码在页面中处于按钮后面,就有可能在一段时间内怎么单击都没反应。

使用dom0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中进行,程序中的this引用当前元素。

<input type="button" value="click me 5" id="button2"/>
var button2=document.getElementById('button2');
	button2.onclick=function(){
	alert(this.id)//button2
}
复制代码

这种方式添加的事件处理程序会在事件流的冒泡阶段被处理

也可以通过dom0级方法指定的事件处理程序,只要像下面这样将事件处理程序属性的值设置为null即可:

btn.onclick=null;//删除事件处理程序
复制代码

设置为null以后,再单击按钮将不会有任何动作发生

3.DOM2级事件处理程序

dom2级事件定义了俩个方法: addEventListener()
removeEventListener()
,分别用于处理指定和删除事件处理程序。所有dom节点都包含这2个方法,并且他们都接受3个参数: 要处理的事件名、作为事件处理程序的函数、一个布尔值
,最后这个参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

<input type="button" value="click me 5" id="button3"/>
var button3=document.getElementById('button3');
button3.addEventListener("click",function(){
		alert(this.id)//button3
},false)
复制代码

与dom0级事件一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行,使用dom2级的好处是可以添加多个事件处理程序。

<input type="button" value="click me 5" id="button3"/>
var button3=document.getElementById('button3');
button3.addEventListener("click",function(){
	alert(this.id)//button3
},false)
button3.addEventListener("click",function(){
	alert(this.value)//click me 5
},false)
//会按次序执行
复制代码

通过addEventListener添加的事件处理程序只能通过removeEventListener来移除,而传入的参数与添加处理程序使用的参数相同,这意味着通过addEventListener添加的匿名函数将无法移除;

button3.addEventListener("click",function(){
	alert(this.value)
},false)
button3.removeEventListener("click",function(){
	alert(this.value)
},false)
//无效,因为传入的匿名函数不一样
复制代码
var handler=function(){
	alert(this.value);
}
button3.addEventListener("click",handler,false);
button3.removeEventListener("click",handler,false);//有效!
复制代码

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

阅读原文...

微信扫一扫,分享到朋友圈

深入理解javascript事件机制
0
稀土掘金

华为已获40个5G商用合同 5G基站全球发货超7万个

上一篇

把你的devtools从webpack里删除

下一篇

评论已经被关闭。

插入图片

热门分类

往期推荐

深入理解javascript事件机制

长按储存图像,分享给朋友