JavaScript 事件流:捕获和冒泡的范围 | 事件监听


事件指可以被 JavaScript 侦测到的行为。
事件流指从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。

事情本来是这样的,

微软IE 的事件流叫做事件冒泡(eventbubbling),微软认为事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
而网景公司的Netscape Navigator的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。

最后w3c就制定了事件流分为三个阶段:

  • 事件捕获:由外向内
  • 目标阶段
  • 事件冒泡:由内向外,当子元素与父元素有相同的事件时,当子元素被触发时父元素也会被触发冒泡机制。

我这个文章主要是解释事件流的范围。 因为之前看到某大厂的面试题问到事件冒泡最后到哪里结束。我不知道答案,结果在网上查,答案也是没个准,只好自己动手。结果都是我自己试出来的。并且参考了《JavaScript高级程序设计》,如果出现问题请指正
在这里插入图片描述

借助两个方法实现事件的监听

  • addEventListener(event,function,useCapture)

    • event:事件,字符串,不需要加上"on",比如鼠标单击事件只需要写"click"
    • function:调用这个方法时要执行的函数
    • useCapture:是否在捕获阶段执行,默认为false,不在事件捕获时执行
    • 不支持IE8及以下版本
  • attachEvent(event,function)

    • event:事件,字符串,需要加上"on",比如鼠标单击事件需要写"onclick"
    • function:调用这个方法时要执行的函数
    • 只支持IE8及以下版本,这个函数无法看到事件捕获阶段(因为从IE4提出事件冒泡之后一直到IE8,IE还坚持己见认为事件流应该是事件冒泡)。
  • 如果你想兼容两种浏览器,那我们自己写一个监听函数呗
    把下面的函数复制到你的代码中即可
    参数:

    • element 你获取到的元素
    • event string类型,你想要监听的时间
    • callback 回调函数
    • bool boolean类型
      • 如果你想监听冒泡阶段就填false
      • 如果你想监听捕获阶段就填true
			function addEvent(element, event, callback, bool) {
				if (element.addEventListener) {
					element.addEventListener(event, callback, bool);
				} else if (element.attachEvent) {
					element.attachEvent('on' + event, callback)
				} 
			}

事件流范围

下面我就介绍一下事件捕获的范围,最后会附代码,可以自己尝试一下。
1. E11-IE9,以及其他浏览器(chrome、Firefox等)都是输出如下图,也就是说:

  • 事件捕获阶段:window-->document-->html-->body-->父元素-->子元素
  • 事件冒泡阶段:子元素-->父元素-->body-->html-->document-->window

事件捕获是从window开始,冒泡过程最后到window结束。
在这里插入图片描述

2. IE8-IE6及以下输出如图,也就是说

  • 事件冒泡阶段:子元素-->父元素-->body-->html-->document

事件冒泡过程最后到document结束。
在这里插入图片描述
解释一下为什么会输出两个,看下边代码就知道了,我用的是上边自定义的监听函数,那个监听函数IE8以下使用attachEvent,不需要布尔类型的参数的,也就是说我写的监听冒泡和捕获的代码都会当作捕获来执行。
但是这样也可以看出,捕获的顺序和代码的位置是没关系的嗷。

3. 还没完。《JavaScript高级程序设计》上说IE5.5及以下的版本,会直接跳过<html>标签,也就是说事件冒泡阶段:子元素-->父元素-->body-->document
但是我实际测验的IE5如下图:子元素-->父元素-->body-->html-->document
但是事件冒泡过程最后也是到document结束。
在这里插入图片描述

代码

CSS:

			#mydiv {
				width: 150px;
				height: 150px;
				padding: 20px;
				background-color: antiquewhite;
			}

			#mypar {
				width: 100px;
				height: 100px;
				background-color: seagreen;
			}

html:

<div id="mydiv">
	<p id="mypar"></p>
</div>

js

			var p = document.getElementById("mypar");
			var div = document.getElementById("mydiv");
			var body = document.getElementsByTagName("body")[0];
			var html = document.getElementsByTagName("html")[0];

			//捕获
			addEvent(p, 'click', function() {console.log('p')}, true);
			addEvent(div, 'click', function() {console.log('div')}, true);
			addEvent(body, 'click', function() {console.log('body')}, true);
			addEvent(html, 'click', function() {console.log('html')}, true);
			addEvent(document, 'click', function() {console.log('document')}, true);
			addEvent(window, 'click', function() {console.log('window')}, true);
			//冒泡
			addEvent(p, 'click', function() {console.log('p')}, false);
			addEvent(div, 'click', function() {console.log('div')}, false);
			addEvent(body, 'click', function() {console.log('body')}, false);
			addEvent(html, 'click', function() {console.log('html')}, false);
			addEvent(document, 'click', function() {console.log('document')}, false);
			addEvent(window, 'click', function() {console.log('window')}, false);

			function addEvent(element, event, callback, bool) {
				if (element.addEventListener) {
					element.addEventListener(event, callback, bool);
				} else if (element.attachEvent) {
					element.attachEvent('on' + event, callback)
				}
			}

我是萝莉安,我爱钻牛角尖

发布了131 篇原创文章 · 获赞 451 · 访问量 54万+

猜你喜欢

转载自blog.csdn.net/qq_36667170/article/details/105032025