javascript之-深入事件机制

作者:yuyuyu
链接:https://zhuanlan.zhihu.com/p/24620643
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.1 事件绑定的方式

原生js的事件绑定方式有几种?想必有很多朋友说3种! 目前,在本人目前的研究中,只有两种半!两种半?还有半种的?且听我道来。

估计大家所认为的三种大概是如下三种:

// 第一种:直接绑定在dom上
<div onclick="fun();">click</div>
// 第二种,使用onclick
document.getElementById("xxx").onclick = function(){

};
// 第三种:使用推荐的标准模式
document.getElementById("xxx").addEventListener("click",function(e){

});

确实,这种方式是在网上搜到的最多的三种方式,但是这里有一个坑,就是当你同时使用三个的时候,第二个会把第一个给覆盖掉,也就是说第一种和第二种是属于同一个方式,只是写法不同,我们可以写一个demo为证:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
	</head>
	<body>
		<button id="btn1" onclick="fun1();">btn</button>
	</body>

	<script type="text/javascript">
		function fun1(){
			console.log("111");
		}

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

		btn.onclick = function(){
			console.log("222");
		}

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

	</script>
</html>

看过我的另一篇博客 深入认识Document 的童鞋应该知道 onclick 是属于Elenent上的一个属性。所谓属性就是指只有一个,重复赋值会覆盖上一次的。但是addEventListener不会,这个方法会绑定多个事件程序,依次执行。

那么那剩下的半种方式到底是什么呢? 我就直接上代码了,毕竟程序猿是一种理解代码能力高于理解文字能力的动物:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
	</head>
	<body>
	  <a id="btn1" onclick="fun1();" href="javascript:fun2();">btn</a>
	</body>

	<script type="text/javascript">
		function fun1(){
			console.log("111");
		}
		function fun2(){
			console.log("222");
		}

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

		btn.addEventListener("click",function(){
			console.log("333");
		});
	</script>
</html>

这下就解释清楚了,为啥是半种,因为使用场景很局限,很多标签用不了。这个时候细心的你可能发现了,这里的顺序也预期的不一样,对 这就是下一个话题了,js事件的执行顺序。

1.2 事件的执行顺序

demo代码就不写了,代码太多,感兴趣的可以直接复制上面你的进行修改,我就说下我得出的结论,

  • a标签的href中的代码总是最后执行,最低的优先级。
  • 无论是 onclick 还是 addEventListener 的执行顺序是按照 绑定的顺序在执行,就是先绑定的就先执行。
  • 如果 onclick 事件被重复绑定,则以最后一次的绑定所在的顺序为准。
  • 如果在DOM中直接使用onclick ,并且没有覆盖,则onclick的绑定是早于 addEventListener 的。
  • 如果绑定多个 addEventListener 事件,在任意一个事件中 stopPropagation(); 都会阻止事件的冒泡,但不会阻止后续事件的执行。

1.3 详解事件对象

老规矩,还是先上代码,先看代码和效果图:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
	</head>
	<body>
		<button id="btn1">btn</button>
	</body>
	<script type="text/javascript">
		var btn = document.getElementById("btn1");

		btn.addEventListener("click",function(event){
			console.log(event);
		});
	</script>
</html>

这时控制台打印了一个 MouseEvent 对象,这个稍微解释一点:

  • clientX、clientY;layerX、layerY;offsetX、offsetY;pageX、pageY;screenX、screenY...... 等等这些都是事件触发的时候的一些相对坐标,有相对屏幕的、相对浏览器的、相对浏览器的、相对父元素、相对当前元素的,这里不多讲,可以自行摆渡。
  • altKey、ctrlKey、shiftKey、metaKey:他们都是返回布尔值,分别表示 按住 alt键、ctrl键、shift键、win键,最后一个meta是windows下的win键,就是位于键盘左下角ctrl和alt之间的那个有windows标志的键,但是在mac上我没有测试,目前这个还没定论,希望有mac机器的同学可以测试一下试试。
  • type:表示事件类型,这里当然是点击了。
  • target:表示事件的触发源,经常在事件冒泡的时候使用,就是使用 event.target 来判断的。
  • timeStamp: 从事件绑定完成到此次事件触发的时间,毫秒单位。
  • path: 事件的冒泡顺序,表示事件是从哪里触发到那个地方结束(这个属性有兼容性问题,我在firefox中没找到这个属性)。
  • 其他的属性就不用一个一个说了,有兴趣的可以仔细翻阅文档。(文章的最后面有地址)

这个时候有的同学可能会问了, 我平时为了阻止事件冒泡和默认事件使用过 stopPropagation和preventDefault方法,这里怎么没有呢?

这个问题问的好,原因是 topPropagation和preventDefault 是Event的方法,而 MouseEvent 是间接的继承了 Event 之后 就可以用这个方法了,那么他是在哪里继承的呢?

我们直接展开浏览器控制台的 MouseEvent 的__proto__ 属性,拉到最底部,发现他还有一个 __proto__ 属性,这个__proto__ 属性的类型是 UIEvent,在继续展开,UIEvent 的 __proto__ 是Event,Event里面就有了这两个方法,熟悉js原型链的同学应该都知道这个。

说白了 就是 MouseEvent 继承了 UIEvent,UIEvent 继承了 Event, Event 继承了 Object。 (这个原型链展开太长了 ,我就不截图了,童鞋们自己测试)

这下,你对事件是不是又有了一个全新的认识。

MouseEvent 事件文档地址

(文章为原创,转载请注明出处)

时间: 2024-07-29 14:06:19

javascript之-深入事件机制的相关文章

JavaScript 详说事件机制之冒泡、捕获、传播、委托

DOM事件流(event  flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 事件捕获(dubbed  bubbling):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件. 事件冒泡(event  capturing):与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点. 无论是事件捕获还是事件冒泡,它们都有一个共同的行为,就是事

JavaScript系列之事件冒泡机制简介

JavaScript系列之事件冒泡机制 DOM事件流(event flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段,事件冒泡顺序是由内到外进行事件传播,事件冒泡是由IE开发团队提出来的,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播. 听了简介介绍之后,您可能不理解,所以举个例子: <html> <head> <title>js事件冒泡测试</title> </head> <body>

jQuery中的事件机制深入浅出

昨天呢,我们大家一起分享了jQuery中的样式选择器,那么今天我们就来看一下jQuery中的事件机制,其实,jQuery中的事件机制与JavaScript中的事件机制区别是不大的,只是,JavaScript中调用是原生的函数方法,而jQuery中调用的绑定的是jQuery中的对象方法,那么在昨天的第一篇中,我们已经说过了jQuery对象和DOM对象之间的转换,至于其中的转换的原理,我们就需要去分析一下jQuery中的源码了,这个我们在源码分析中再去做讨论, 首先呢,我们先来看一下,jQuery中

JavaScript事件机制

<script type="text/javascript" src="http://runjs.cn/gist/2zmltkfa/all"></script> [前端培养-作业01]javascript事件机制 1.javascript事件模型 2.e.target与e.currentTarget是干什么的? 3.preventDefault与stopPropagation是干什么的 4.什么是dispatchEvent? 5.说一说事件代

javascript的事件机制

一.事件模型 IE 和 标准DOM的事件模型 IE系:冒泡方式 NETSCAPE系:捕获方式 标准DOM:先捕获再冒泡 冒泡,从触发点向外层.顶层扩散,最后到达document.window,遇到相同注册事件立即触发执行: 捕获则相反,从window.document向里收缩,一直到触发点,遇到相同注册事件立即触发执行: 有代码如下: <style type="text/css"> div { border: solid 1px red; } #s1 { padding:

javascript事件机制了解与深入

一.事件的捕获与冒泡 “DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段.处于目标阶段和事件冒泡阶段.下面这个图能够很形象的解释(理解捕获和冒泡必不可少的图) 按照图我们编写了代码去验证下, <div id="parent"> <div id="child"> child </div> </div> <script type="text/javascript"> var p = d

[解惑]JavaScript事件机制

[解惑]JavaScript事件机制 初学 JS 的童鞋经常会有诸多疑问,我在很多 QQ 群也混了好几年了,耳濡目染也也收获了不少,以后会总结下问题的结论,顺便说说相关知识的扩展~ 如果贸然回答还会冒泡,这不太好的,稍微严谨点考虑 0级 DOM 事件模型的话,这个答案是否定的.但是在 2级 DOM 事件模型中,答案是肯定的,这个问题值得探讨记录下. 本文地址:http://www.cnblogs.com/hustskyking/p/problem-javascript-event.html 一.

Javascript事件机制兼容性解决方案

原文:Javascript事件机制兼容性解决方案 本文的解决方案可以用于Javascript native对象和宿主对象(dom元素),通过以下的方式来绑定和触发事件: 或者 var input = document.getElementsByTagName('input')[0]; var form = document.getElementsByTagName('form')[0]; Evt.on(input, 'click', function(evt){ console.log('inp

深入研究JavaScript的事件机制

本篇开始将回顾下Javascript的事件机制.同时会从一个最小的函数开始写到最后一个具有完整功能的,强大的事件模块.为叙述方便将响应函数/回调函数/事件Listener/事件handler都称为事件handler.天台县羿壮冶金 先看看页面中添加事件的几种方式: 直接将JS代码写在HTML上 测试:Nowamagic view source print? 1 <div onclick="alert('欢迎访问Nowamagic.net');">Nowamagic</