专栏名称: klivitamJ
android/前端工程师
目录
相关文章推荐
南方能源观察  ·  新能源全面入市新政出炉 ·  昨天  
能源电力说  ·  发改委、能源局印发:抽水蓄能重磅文件! ·  3 天前  
南方能源观察  ·  2024年广东新能源产业集群营收破万亿,达1 ... ·  4 天前  
Quora文选英语  ·  老外说up to no ... ·  4 天前  
51好读  ›  专栏  ›  klivitamJ

关于前端事件的那些事儿

klivitamJ  · 掘金  ·  · 2019-05-17 14:18

正文

阅读 13

关于前端事件的那些事儿

事件这个东西呢?是一个很神奇的东西,搞的我很烦 无论是在Android端还是前端。今天巧借这点时间呢?就准备来写一写这个东西。先写一篇前端的事件,然后再转向Android端写一篇Android端的事件 perfect...

一、 什么叫事件流

事件流的描述呢?很简单:就是描述从页面接收到事件的顺序。现今主流的两大阵营对此提出了两种相反的事件流:ie提出的称之为事件冒泡;Netscape communicator提出的则是事件捕获。那么什么是事件冒泡和事件捕获呢?

  • 事件冒泡

IE的事件流叫做事件冒泡,说白了冒泡就是从嵌套最深的那个节点接收,然后逐级向上冒泡直到document的过程。用下面的html为例子:

<!DOCTYPE html>
<html>
<head>
	<title>我是测试</title>
</head>
<body>
	<div >click Me</div>
</body>
</html>
复制代码

如果你单击了div元素,那么这个click事件就这么传递: 1、 div 2、 body 3、 html 4、document 也就是说,当我们点击了div元素之后,click事件首先在div元素上面发生,这个元素就是我们单击的元素。然后click事件就顺着DOM树向上传播,在每一级上面都会发生,一直传到document。

  • 事件捕获

Netscape communicator团队提出了另一种事件流叫做事件捕获。事件捕获的过程呢?则是从document开始一直传递到div的过程: 1、document 2、 html 3、 body 4、 div 示意图如下:

  • DOM的事件流

通常的事件流包括三个步骤:事件捕获阶段、处于目标阶段和事件冒泡阶段。用前面的html表示,大概就是这样。

事件在处于捕获阶段的时候呢?是不会接收到事件的,然后再目标阶段的时候,事件发生在div元素中,然后通过冒泡传回文档流

二、 事件的处理程序

事件呢?就是:用户或者浏览器自身执行的某种动作。比如click,load和mouseover。而相应某个事件的函数叫做事件处理程序。一般都是 on 开头的,onclick就是click的处理程序、onload就是load的处理程序等等... 首先 我们直接用代码来写主要的几种类型:

1、 html事件处理程序:

	<button id="myBtn1" onclick="showMessage()">我是 html事件处理程序</button>

    function showMessage(){
      alert("hello my friends!")
	}
复制代码

2、 Dom0事件处理程序:

		<button id="myBtn2">我是dom0事件处理程序</button>

        var btn2 = document.getElementById("myBtn2");
		btn.onclick = function(){
		  alert("hello my friends!");
		}
        btn.onclick = null;  //移除事件
复制代码

3、 Dom2事件处理程序:

这里和前面不同,dom2定义了两个方法:addEventListener()和removeEventListener()分别用来绑定和删除事件。所有的dom节点都包含这个方法,并且它接受三个参数:处理的事件名、作为事件处理的函数和一个布尔值。如果这个布尔值是true,表示在捕获阶段调用事件程序;如果是false,则表示在冒泡阶段调用事件处理程序。

事件绑定如下:

	<button id="myBtn">我是dom2事件处理程序</button>

    var btn = document.getElementById("myBtn");
	btn.addEventListener("click",function(){
		alert("hello klivitam!")
	},false)
复制代码

关于事件绑定和移除有这么几个要注意的点:

  • 事件多次绑定
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function(){
	alert("hello klivitam!")
},false)

btn.addEventListener("click",function(){
	alert("123456")
},false)
复制代码

如果重复进行添加事件的话,这样会先出按照顺序 先显示 hello klivitam ,然后再显示 123456

  • 事件移除 先看下面一段代码
		var btn = document.getElementById("myBtn");
		btn.addEventListener("click",function(){
			alert("hello klivitam!")
		},false)

		btn.removeEventListener("click",function(){
			alert("hello klivitam!")
		},false)
复制代码

我们知道:利用addEventListener()绑定的事件,需要用removeEventListener()来将事件的监听移除,并且removeEventListener()的参数必须和addEventListener()的参数相同。这里我们虽然看似两者是相同的,但是并不能移除。这是值得注意的,针对这种情况,我们应该这么写:

		var handle = function(){
			alert("hello klivitam!")
		}
		var btn = document.getElementById("myBtn");
		btn.addEventListener("click",handle,false)

		btn.removeEventListener("click",handle,false)
复制代码

3、 IE事件处理程序:

ie中存在和dom中想同的两个方法:attachEvent和detachEvent。这两个方法接受想同的两个参数:事件处理程序的名称与事件处理程序函数。 首先我们先写一个绑定的实例:

		var btn2 = document.getElementById("myBtn2");

		btn2.attachEvent("onclick",function(){
			alert(window === this);
		})

		btn2.attachEvent("onclick",function(){
			alert("boy");
		})
复制代码

同样和dom2的一样的操作,这里只不过函数名变了。这里值得注意的是: window和this相等 。当点击btn2元素的时候,首先会提示true,然后再提示boy。并且在移除代码的时候,和dom2的操作一样

		var btn2 = document.getElementById("myBtn2");

		var handle = function(){
			alert("hello klivitam!")
		}

		btn2.attachEvent("onclick",handle)

		btn2.detachEvent("onclick",handle)
复制代码

4、 跨浏览器的事件处理程序:

前面说了这么多方面的事件处理程序,那么我们在进行开发的时候很可能会需要适配很多浏览器。我们在每次事件绑定的时候,肯定要考虑到诸多版本,诸多内核的浏览器。为了解决这种逻辑,我们就可以进行封装处理。我在这里是这样进行处理的:

		var EventUtils = {
			addHandler:function(ele,type,hander){
				if(ele.addEventListener){
					ele.addEventListener(type,hander,false);
				}else if(ele.attachEvent){
					ele.attachEvent("on"+type,hander);
				}else{
					ele["on"+type] = hander;
				}
			}

			removeHandler:function(ele,type,hander){
				if(ele.removeEventListener){
					ele.removeEventListener(type,hander,false);
				}else if(ele.detachEvent){
					ele.detachEvent("on"+type,hander);
				}else{
					ele["on"+type] = null;
				}
			}
		}
复制代码

首先,我们在绑定事件的时候呢?绑定事件的时候首先判断是否支持dom2的事件处理程序,如果不支持,那么继续判断是否支持ie的事件处理程序,如若还不支持就只能用通用的事件处理程序。解绑的时候也是一样,先判断是否支持dom2事件处理程序,接着判断ie的事件处理程序,最后在都不支持的情况下使用通用的事件处理程序。

我们在使用的时候就可以这样写一下就好了:

		var btn2 = document.getElementById("myBtn2");

		var handle = function(){
			alert("hello klivitam!");
		}

		EventUtils.addHandler(btn2,"click",hander);

		EventUtils.removeHandler(btn,"click",hander);
复制代码

当然这个封装还室友点瑕疵的,比如不知道this的指向等等,当然 我在后续的文章中会继续的去讨论封装这个组件的。

三、 事件的对象

我们知道在触发dom上的某个事件对象的时候,这个对象会包含着所有与事件有关的信息。包括事件的元素、事件的类型以及其他与特定事件相关的信息。

  • dom的事件对象

兼容dom的浏览器会将一个event对象传到事件处理程序中。例如:

		btn.addEventListener("click",function(e){
			console.log(e);
		},false)

		btn.onclick = function(e){
			console.log(e);
		};
复制代码

上图是我打印出来传递的event对象中所包含的值。我在这里呢?就简单的介绍几个最基本的含义,剩下的其实大多数大家都能看懂。

属性/方法 类型 读写 说明
bubbles boolean 只读 表明事件是否冒泡
cancelable boolean 只读 表明是否可以取消事件的默认行为
currentTarget Element 只读 其事件的处理程序正在处理程序的那个元素
defaultPrevented boolean 只读 为true表示已经调用了preventDefault(dom3新增的)
detail Integer 只读 与事件相关的详细细节
eventPhase Integer 只读 调用事件处理程序的阶段:1表示捕获,2处于目标,3处于冒泡
preventDefault() Function 只读 取消事件的 默认行为,如果cancelable为true才能使用这个方法
stopImmediatePropagation Function 只读 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(dom3新增)
stopPropagation Function 只读 取消事件的进一步捕获或者冒泡。如果cancelable为true的时候,才能使用这个方法
target Element 只读 事件的目标
trusted Boolean 只读 为true表示事件是浏览器生成的。为false表示事件又开发者通过js创建的(dom3新增的)
type String 只读 被触发事件的类型
view abstractview 只读 与事件相关联的抽象视图,等同于发生事件的window对象

上面表格中值得注意三点的就是:

  • this是始终等于currentTarget的值,而target则只包含事件的实际目标







请到「今天看啥」查看全文