事件冒泡原理自我理解以及使用

来源:互联网 发布:韦德生涯数据更新 编辑:程序博客网 时间:2024/06/08 15:49

首先,这是我自己在学习过程中对于时间冒泡原理的理解,如果有不对的地方,读者尽可提出,不断学习。

一:事件冒泡和阻止冒泡以及使用场景:

1.事件冒泡,就是元素自身的事件被触发后,如果父元素有相同的事件,如onclick事件,那么元素本身的触发状态就会传递,也就是冒到父元素,父元素的相同事件也会一级一级根据嵌套关系向外触发,直到document/window,冒泡过程结束。

2.比如:

<div class="box" styel="width:200px; height: 200px;background_color:'#ddd'">

<div class="box1" styel="width:200px; height: 200px;background_color:'#000'>

<div class="box2" styel="width:200px; height: 200px;background_color:'#eee'></div>

</div>

</div>

<script>

document.querySelector(".box").onclick=function(){

alert("我是box")

}

document.querySelector(".box1").onclick=function(){

alert("我是box1")

}

document.querySelector(".box2").onclick=function(){

alert("我是box2")

}

document.onclick=function(){

alert("我是document")

}

</script>

此时触发box2中的额onclick事件,会依次弹出“我是box2” 我是box1 我是box1 我是document。这就是事件冒泡。

3.但是事件冒泡在某些应用场景产生一些问题,就是我们不需要触发的事件,由于冒泡的原因,也会运行。所以在这个时候要取消事件冒泡。直接粘图(不知道用什么工具直接粘贴代码,带原格式的。。。)

    box.onmouseover = function (event) {
        // 阻止冒泡
        event = event || window.event;
        if(event && event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble = true;
        }
    }

4.那么事件冒泡和组织冒泡什么时候会用到呢?

记着只要是能够触发事件冒泡的情况下,就考虑取消事件冒泡,或者直接利用事件冒泡。

在这里,有一个例子,可以实现阻止事件冒泡来实现,就是模态框的显示和隐藏:(模态框不懂自行参考)。

    <div class="mask">
        <div class="login" id="login"></div>
    </div>
    <a href="#">注册</a>
    <a href="#">登陆</a>
    <script>
        //1.给登录绑定事件
        var mask = document.getElementsByClassName("mask")[0];
        var a = document.getElementsByTagName("a")[1];
        a.onclick = function (event) {
            //显示模态框
             ele.style.display = "block";
            //阻止冒泡
            event = event || window.event;
            if(event && event.stopPropagation){
                event.stopPropagation();
            }else{
                event.cancelBubble = true;
            }
        }
        //2.给document绑定事件,因为可以冒泡,只要判断,点击的不是login,那么隐藏模态框
           document.onclick = function (event) {
            // 获取点击按钮后传递过来的值。
            event = event || window.event;
            //兼容获取事件触动时,被传递过来的对象
           var aaa = event.target || event.srcElement;
            var aaa = event.target?event.target:event.srcElement;
            console.log(event.target);
            //判断目标值的ID是否等于login,如果等于不隐藏盒子,否则隐藏盒子。
            if(aaa.id !== "login"){
                mask.style.display = "none";
            }
            alert("123")
        }
    </script>

解释:因为document和a都绑定了onclick事件,而且是嵌套的关系,当点击a标签的时候,会造成事件冒泡,既会显示mask模态框,又会弹出“123”的弹出框,所以我们要组织事件的冒泡。如上。

然后判断点击的对象target是不是mask,如果不是mask,就运行mask.style.display="none",模态框消失。

二:事件委托:

1.刚开始接触事件委托概念的时候,很是懵逼,搞不懂到底是一个怎样的委托过程,怎么实现的,但是学到一定程度回过头来,也感觉很好理解。

个人认为事件冒泡存在的意义,就是在事件运行过程中,避免使用循环遍历的方式去给每个同级元素触发相同的事件,而优化性能。要知道,元素量无限大,循环遍历是个噩梦,这也是网站性能优化的一个方面,就是尽量减少使用循环遍历。好了,简单说说我对事件委托理解,实例是摘抄过来的:

如果要实现列表中,当鼠标over的时候,给每个li添加背景:一般想到的方法就是循环遍历添加,如下:

<ul id="ul"><li>aaaaaaaa</li><li>bbbbbbbb</li><li>cccccccc</li></ul>
window.onload = function(){var oUl = document.getElementById("ul");var aLi = oUl.getElementsByTagName("li");for(var i=0; i<aLi.length; i++){aLi[i].onmouseover = function(){this.style.background = "red";}aLi[i].onmouseout = function(){this.style.background = "";}}}
在元素个数不多的情况下可以使用,但元素很多的时候,不建议使用,建议使用冒泡的事件委托:原理如下:

window.onload = function(){var oUl = document.getElementById("ul");var aLi = oUl.getElementsByTagName("li");/*这里要用到事件源:event 对象,事件源,不管在哪个事件中,只要你操作的那个元素就是事件源。ie:window.event.srcElement标准下:event.targetnodeName:找到元素的标签名*/oUl.onmouseover = function(ev){var ev = ev || window.event;var target = ev.target || ev.srcElement;//alert(target.innerHTML);if(target.nodeName.toLowerCase() == "li"){target.style.background = "red";}}oUl.onmouseout = function(ev){var ev = ev || window.event;var target = ev.target || ev.srcElement;//alert(target.innerHTML);if(target.nodeName.toLowerCase() == "li"){target.style.background = "";}}}
只要判断over或者out的对象,nodeName是不是"li",是的话就添加或者去掉背景。

2.还有一种情况:就是新添加的元素:

我们通常会使用Document.createElement("li");创建新的元素,然后再appendChild添加到父标签中。但是有这样一种情况,我是循环遍历给每个li标签绑定了鼠标悬停现实背景色的事件,但这样,新添加的元素就不会被循环到,因为添加之前已经循环停止了:所以:使用事件委托,就很好的解决了这个问题:

window.onload = function(){var oUl = document.getElementById("ul");var aLi = oUl.getElementsByTagName("li");var oBtn = document.getElementById("btn");var iNow = 4;oUl.onmouseover = function(ev){var ev = ev || window.event;var target = ev.target || ev.srcElement;//alert(target.innerHTML);if(target.nodeName.toLowerCase() == "li"){target.style.background = "red";}}oUl.onmouseout = function(ev){var ev = ev || window.event;var target = ev.target || ev.srcElement;//alert(target.innerHTML);if(target.nodeName.toLowerCase() == "li"){target.style.background = "";}}oBtn.onclick = function(){iNow ++;var oLi = document.createElement("li");oLi.innerHTML = 1111 *iNow;oUl.appendChild(oLi);}}


原创粉丝点击