Javascript笔记—事件分析(冒泡,捕获,代理)

1.事件冒泡

事件冒泡机制:事件冒泡基本原理是事件从特定的目标对象向不特定的目标对象进行触发,简单点就是从触发事件开始的元素开始向上冒泡。


同时不同浏览器版本,事件冒泡触发的最终位置或经过的元素是不一样的。如下所示:
IE 5.5: div -> body -> document
IE 6.0: div -> body -> html -> document
Mozilla 1.0: div -> body -> html -> document -> window
事件冒泡实现代码:(由于addEventListener()方法IE不支持,所以以下代码不支持IE效果预览)。如果直接在html标签中使用onclick事件(<div onclick="func()"></div>),将发生事件捕获(本人只测试过IE8+,火狐,谷歌浏览器。如果有问题可以在下面留言我第一时间进行补充)。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
	body,html {padding:0px;margin: 0px;}
	#myDiv {width:400px;height:400px;padding:0px;margin:0px;background: #eee;}
	#three {width: 300px;height: 300px;background: #ccc;}
	#two {width: 200px;height: 200px;background: #999;}
	#one {width: 100px;height: 100px;background: #666;}
</style>
</head>

<body>
<div id="myDiv">
	<div id="three">
		<div id="two">
			<div id="one"></div>
		</div>
	</div>
</div>
</body>
<script type="text/javascript">
	var oneDom=document.getElementById("one");
	var twoDom=document.getElementById("two");
	var threeDom=document.getElementById("three");
	var imgDom=document.getElementById("myDiv");
	function auto1(){
		alert(1);
	}
	function auto2(){
		alert(2);
	}
	function auto3(){
		alert(3);
	}
	function auto4(){
		alert(4);
	}
	oneDom.addEventListener("click",auto1,false);
	twoDom.addEventListener("click",auto2,false);
	threeDom.addEventListener("click",auto3,false);
	imgDom.addEventListener("click",auto4,false);
</script>
</html>
2.事件捕获
事件捕获的原理跟时间冒泡的原理正好是相反的,它是从最不特定的元素向特定的元素向下进行捕获



只要将上述代码addEventListener()中的第三个参数改为true即可看到时间捕获效果。
补充知识:DOM事件流—DOM事件流同时支持事件捕获和事件冒泡,原理是先发生事件捕获在进行事件冒泡。


3.事件代理
事件代理机制:事件代理是由于浏览器的冒泡机制引起的,当多个DOM元素需要绑定事件的时候(也就是多个事件),你可以把该事件委托给父元素来触发(变成了一个事件了)。简而言之,“代理”这个词可以片面理解为自己的事情让别人帮你做。

代码效果:“事件代理”实现列表li标签背景色切换效果。

代码效果一(传统方式):

<!doctyp html>
<html>
<head>
<meta charset="utf-8">
<title>传统方式</title>
<style type="text/css">
    html,body{padding:0px;margin: 0px;background: #eee;font-size:62.5%;font-family: "微软雅黑";}
    #ulDom {
        width:200px;
        background: #fff;
        list-style: none;
        position: absolute;
        left: 0px;
        right: 0px;
        padding:0px;
        margin: 100px auto;
    }
    #ulDom li {
        font-size: 2em;
        padding:15px;
        border-bottom:1px solid #ccc;
    }
    #ulDom li:last-child {
        border:none;
    }
</style>
<script language="javascript">
    window.onload=function(){
        //传统的写法
        var idDom=document.getElementById("ulDom");
        console.time(1);
        var liObj=document.getElementsByTagName("li");
        for(var i=0,len=liObj.length;i<len;i++){
            (function(i){
                liObj[i].onmouseover=function(){
                    this.style.background="#ccc";
                }
                liObj[i].onmouseout=function(){
                    this.style.background="none";
                }
            })(i);
        }
        console.timeEnd(1);
    }
</script>
</head>

<body>
    <ul id="ulDom">
        <li>HTML&CSS</li>
        <li>HTML5&CSS3</li>
        <li>Javascript</li>
        <li>Jquery</li>
    </ul>
</body>
</html>
代码效果二(事件代理方式):

<!doctyp html>
<html>
<head>
<meta charset="utf-8">
<title>事件委托</title>
<style type="text/css">
    html,body{padding:0px;margin: 0px;background: #eee;font-size:62.5%;font-family: "微软雅黑";}
    #ulDom {
        width:200px;
        background: #fff;
        list-style: none;
        position: absolute;
        left: 0px;
        right: 0px;
        padding:0px;
        margin: 100px auto;
    }
    #ulDom li {
        font-size: 2em;
        padding:15px;
        border-bottom:1px solid #ccc;
    }
    #ulDom li:last-child {
        border:none;
    }
</style>
<script language="javascript">
    window.onload=function(){
        //传统的写法
        var idDom=document.getElementById("ulDom");
        //事件代理(委托)
        console.time(2);
        idDom.onmouseover=function(e){
            var e=e || window.event;
            var target=e.target || e.srcElement;
            if(target.nodeName.toLowerCase() == "li"){
                target.style.background="#ccc";
            }
        }
        idDom.onmouseout=function(e){
            var e=e || window.event;
            var target=e.target || e.srcElement;
            if(target.nodeName.toLowerCase() == "li"){
                target.style.background="none";
            }
        }
        console.timeEnd(2);   
    }
</script>
</head>

<body>
    <ul id="ulDom">
        <li>HTML&CSS</li>
        <li>HTML5&CSS3</li>
        <li>Javascript</li>
        <li>Jquery</li>
    </ul>
</body>
</html>
上述代码中的console.time()与console.timeEnd()方法主要用来查看被包围代码的运行时间。
“代码一”的实现方式是给ul标签中的所有li子标签都绑定了事件,如果li标签比较多的话,“代码一”就会变的不简洁。而“代码二”中只给父元素ul标签绑定了事件,就可以实现效果。这种实现原理是利用“冒泡机制”实现,单击子标签时,事件就会冒泡到父标签并触发事件。然后再做相应的判断就可以实现子标签的效果。
事件代理机制的优势:
1.代码运行时间相对比较快
2.代码比较简洁。

代码效果一(传统方式):

猜你喜欢

转载自blog.csdn.net/u012475786/article/details/53691754