事件流
事件流事件流,可以拆分为事件和流,事件(事件通常与函数配合使用,这样就可以通过发生的事件来驱动函数执行。)——鼠标点击、鼠标移动至、加载等等等等,正因为有了事件,js才能与dom建立起联系,说到dom不免扯开来去解释一下
dom:文档对象模型(Document Object Model,简称DOM)(我可真官方。。),其实稍微通俗点就是我们的html标签在被浏览器渲染的时候会生成一棵标签树,我们可以把这棵由标签构成的树别名称之为文档树或者文档,而每一个标签在js中都可以被抽象成一个对象,因此文档对象模型又可以简单的理解为html标签文档在js中的对象映射。
文档树的理解:window->document->html->head/body->内部其他标签
- 凡出现在html中的标签被浏览器解析的时候都会被挂载到dom树上。
- dom树上的每个标签都是一个独立的对象,既然是对象就会有属性和方法,上文也提到过事件通常与方法不离不弃,所以这里我们就会晓得一个基本常识了,事件一般会和标签和方法挂钩,我们通常在标签上注册一个事件,当事件满足条件被触发以后就会执行我们早些预定义好的方法。
- 事件的概念就是:让html在某些特定条件下执行了一段js脚本,某些特定的条件就是如单击,双击,鼠标经过等,这些条件以属性的形式呈现在html代码中,而触发执行的js脚本则通常为方法。
那流又是什么呢,水流水流,让水进行一个有方向的运动,对就是方向。
事件流就是让事件有一个方向进行发生,即描述的是从页面中接收事件的顺序。
接下来话不多说,直接上代码:
<style>
#outcircle{
width: 400px;
height: 400px;
background-color: blueviolet;
}
#centercircle{
width: 300px;
height: 300px;
background-color: brown;
top: 50%;
left: 50%;
margin-left: -150px;
margin-top: -150px;
}
#innercircle{
width: 200px;
height: 200px;
background-color: aqua;
top: 50%;
left: 50%;
margin-left: -100px;
margin-top: -100px;
text-align:center;
line-height: 200px;
}
#outcircle,#centercircle,#innercircle{
position: absolute;
border-radius: 100%; //圆角处理
}
</style>
<body>
<div id="outcircle">
<div id="centercircle">
<div id="innercircle">
点我!
</div>
</div>
</div>
</body>
<script>
var innerCircle = document.getElementById("innercircle");
innerCircle.onclick= function () {
alert("innerCircle");
};
var middleCircle = document.getElementById("centercircle");
middleCircle.onclick=function(){
alert("middleCircle");
}
var outerCircle = document.getElementById("outcircle");
outerCircle.onclick= function () {
alert("outerCircle");
}
</script>
从结构上可以看出,他是三个div块相互嵌套,当我们对最里面的 innercircle 进行事件click触发时,结果而言 centercircle 与outcircle 也被进行事件的触发了,这到底是怎么回事呢。没错,这就是接下来要讲的事件流的其中一种:冒泡型事件流
首先,事件流分为冒泡型事件流与捕获型事件流
然后,从网上biu张经典事件流图
从图中我们可以知道
1、一个完整的JS事件流是从window开始,最后回到window的一个过程
2、事件流被分为三个阶段(1-5)捕获过程,(5-6)目标过程,(6-10)冒泡过程
然而在有些情况下JS的事件流不会根据上图这个从捕获过程到目标过程到冒泡过程这样去推进的(dom level等会说)
DOM level | 捕获事件 | 冒泡事件 |
---|---|---|
DOM level 0 | 不支持 | 支持 |
DOM level 2 | 支持 | 支持 |
DOM level 3 | 支持 | 支持 |
事件捕获:什么叫捕获,就是从最不具体的到最具体的
事件冒泡:什么叫冒泡,正好和上面相反,从最具体的到最不具体的
不管冒泡还是捕获其的传递范围一定是父子关系,也就是外层到内层,或者从内层到外层。假设我们给div添加一个事件方法,如果是事件捕获的话是从window开始,因为他是最不具体的元素,如果是冒泡的话则是从div开始到window
补充:捕获和冒泡的方式决定着浏览器何时去处理这个事件,如果我把事件声明在冒泡阶段处理,那么在捕获阶段即使捕获到了这个事件,事件也是不会被执行,冒泡同理
<div id="one">
<div id="two">
<div id="three"></div>
</div>
</div>
one.addEventListener('click',function(e){
console.log('one');
},false);
two.addEventListener('click',function(e){
console.log('two');
},false);
three.addEventListener('click',function(e){
console.log('three');
},true);
补充一句:addEventListener()中可以添加三个参数,其中最后一个布尔值代表浏览器执行何种事件流处理方式,true为捕获,false为冒泡
那么在上方的代码中,one与two为冒泡事件,而three为捕获,关键来了,现代浏览器对于事件的处理一定是先捕获后冒泡,因此在浏览器全部加载完这段js代码时,即使three这个所在的div是one与two的子元素,但由于它是归为捕获事件处理,而它的父元素为冒泡事件,则three仍会被优先处理,最后输出的结果为 three 再是 two one。
补充一句:在jQuery中对于事件的处理采取的方式与原生js略有不同,对于事件的处理采用事件绑定来进行控制,而且为了兼容所有的浏览器,因此jQuery中大多数只存在冒泡与阻止冒泡事件(可能我未必了解完全)。
关于DOM level
dom level 0
<body>
<div style="width:200px;height:200px;background:lightblue" id="content">
<div style="width:100px;height:100px;background: lightyellow;" id="btn1">
</div>
</div>
</body>
js部分
var btn1=document.getElementById("btn1");
var content=document.getElementById("content");
btn1.onclick=function(){
alert("btn1_click");
}
btn1.onclick=function(){
alert("btn1_click2");
}
content.onclick=function(){
alert("content_click");
}
运行的结果是先弹出btn1_click2,然后弹出content_click,从这里案例我们可以得出这几点:
1、btn1_click这个事件没有被触发,所以在DOM Level 0中的只能一个元素只能绑定一个事件,并且绑定的是最后绑定的那个事件,这个有点像jquery中的html方法一样,后面的会覆盖掉前面的内容一样
2、content_click的触发也同时也证明了DOM Level 0不会阻止事件冒泡的发生
dom level 2
var btn1=document.getElementById("btn1");
var content=document.getElementById("content");
btn1.addEventListener("click",function(){
alert("btn1");
},false);
btn1.addEventListener("click",function(){
alert("btn2");
},false);
content.addEventListener("click",function(){
alert("content");
},false);
运行的结果是:先弹出btn1,然后弹出btn2,最后弹出content ,运行的结果我们可以分析出来:
DOM Level 2可以在一个元素上面注册一个事件的时候在注册另外一个事件,也就是可以同时在一个元素上面存在多个事件
DOM Level 0与DOM Level 2的主要区别去了上面说的一点外还有以下的几点:
1、DOM Level 2可以在一个元素上面注册多个事件,但是DOM Level 0就不可以
2、DOM Level 0的兼容性好,可以支持所有的浏览器,但是DOM Level 2中的addEventListener的这个方法在IE浏览器是不支持的,IE浏览器支持attachEvent事件,attachEvent事件支持两个参数,第一个是事件类型,第二个是执行的函数,DOM Level 0不同于addEventListener,这个在使用的时候要加上on,例如:addEventListener的单击事件是click,而attachEvent的单击事件是onclick,由于IE只支持冒泡事件,所以没有第三个参数
3、DOM Level 2在IE中的绑定事件是attachEvent,解除绑定是detachEvent,在标准的浏览器绑定事件是addEventListener,解除绑定是removeEventListener
关于dom level 3有兴趣可以自己百度Google了解下,分类更加多和全面