一、什么是JavaScript事件流?
原文博客:https://www.cnblogs.com/st-leslie/p/5907556.html(写得非常好)
//举例
<body>
<div style="width:200px;height:200px;background:lightblue" id="content">
<div style="width:100px;height:100px;background: lightyellow;" id="btn1">
</div>
</div>
</body>
<script type="text/javascript">
var content=document.getElementById("content");
var btn1=document.getElementById('btn1');
btn1.onclick=function(){
alert("btn1");
};
content.onclick=function(){
alert("content");
}
</script>
从图中我们可以知道
1、一个完整的JS事件流是从window开始,最后回到window的一个过程
2、事件流被分为三个阶段(1~5)捕获过程、(5~6)目标过程、(6~10)冒泡过程
3、在冒泡过程中6比7早触发,也就解释了上面那题,为什么btn1,会比content先触发
二、stopPropagation()与preventDefault()的区别
1、preventDefault()主要是用来阻止标签的默认行为,如:阻止了a标签的打开新窗口。
2、stopPropagation()这个方法主要是用来阻止事件冒泡的,
var btn1=document.getElementById("btn1");
var content=document.getElementById("content");
btn1.addEventListener("click",function(event){
alert("btn1");
event.stopPropagation();
},false);
content.addEventListener("click",function(){
alert("content");
},false);
这一段代码就阻止了id="btn1"向上级id="content"上面冒泡,打印出来的结果是:弹窗弹出btn1。
三、事件委托
参考文章:https://www.cnblogs.com/liugang-vip/p/5616484.html(写的很详细)
1、什么叫事件委托?
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
2、为什么要用事件委托?
dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那如果是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢?
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能。
3、事假委托原理?
就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
这里用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发,当然,这里当点击ul的时候,也是会触发的,那么问题就来了,如果我想让事件代理的效果跟直接给节点的事件效果一样怎么办,比如说只有点击li才会触发,不怕,我们有绝招:
Event对象提供了一个属性叫target,可以返回事件的目标节点,我们称为事件源,也就是说,target就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用ev.target,IE浏览器用event.srcElement,此时只是获取了当前节点的位置,并不知道是什么节点名称。
window.onload = function(){
var oUl = document.getElementById("ul1");
oUl.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
alert(123);
alert(target.innerHTML);
}
}
}