文章目录
事件指可以被 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)
}
}
我是萝莉安,我爱钻牛角尖