1. 程式人生 > >事件委託/事件冒泡/事件捕獲&&阻止事件冒泡/阻止事件預設行為

事件委託/事件冒泡/事件捕獲&&阻止事件冒泡/阻止事件預設行為

要了解事件委託,首先要了解事件流的概念和事件執行流程:

DOM2級中同時支援兩種事件模型:捕獲型事件和冒泡型事件 ,並且每當某一事件發生時,都會經過捕獲階段->處理階段->冒泡階段(有些瀏覽器不支援捕獲) ;事件的捕獲階段是由上層元素到下層元素的順序依次。而冒泡階段則正相反。


當事件觸發時body會先得到有事件發生的資訊,然後依次往下傳遞,直到到達最詳細的元素,這就是事件捕獲階段。 
還記得事件註冊方法ele.addEventListener(type,handler,flag)吧,Flag是一個Boolean值,true表示事件捕捉階段執行,false表示事件冒泡階段執行,預設為false。 


接著就是事件冒泡階段。從下往上 依次執行事件處理函式(當然前提是當前元素為該事件註冊了事件控制代碼)。,在這個過程中,可以阻止事件的冒泡,即停止向上的傳遞。 

想一個例子:你一定有過經歷,給一個ul的所有li新增點選事件,然後用了一個迴圈,給每個li都添加了onclick監聽事件,這是很危險的做法,理論上,如果li足夠多,就足以造成點選某個li的一瞬間瀏覽器崩潰。所以這時候就要用到事件捕獲,將點選事件繫結在li的父元素中,當點選事件發生時,父元素會在其子元素中層層查詢一直到達觸發事件那個最詳細元素的位置(即觸發事件的最內層元素),下面是一個例子,大家可以參考一下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡/事件捕獲&&阻止事件冒泡/阻止事件預設行為</title>
    <style>
        div.div_in{
            width: 200px;
            height: 100px;
            border: solid red 1px;
        }
        div.div_in_in{
            width: 150px;
            height: 50px;
            border:1px solid black;
        }
    </style>
</head>
<body>
    <div id="div_one" onclick="eventHandle(event)">
        <ul id="ul_one">
            <li id="li_one"><div id="one" class="div_in">1</div></li>
            <li id="li_two"><div id="two" class="div_in">2</div></li>
            <li id="li_three"><div id="three" class="div_in">3</div></li>
        </ul>
    </div>
    <div id="div_two">
        <ul id="ul_two">
            <li id="li_four">
                <div id="four" class="div_in" onclick="showNum('11111')">4
                    <div id="seven" class="div_in_in" onclick="showNum('22222')">7</div> <!-- 當該元素被點選時,彈出兩個框,是由於onclick事件在當前div觸發的同時又冒泡到其外層div,同時觸發了外層div的onclick事件 -->
                </div>
            </li>
            <li id="li_five">
                <div id="five" class="div_in">5
                    <a href="http://www.baidu.com" target="_blank" onclick="notTurnToHerf(event)">turn to www.baidu.com</a>
                </div>
            </li>
            <li id="li_six">
                <div id="six" class="div_in" onclick="showNumStop(event,'33333')">6
                    <div id="eight" class="div_in_in" onclick="showNumStop(event,'44444')">8</div> <!-- 當該元素被點選時,只彈出“44444”框,因為冒泡事件被以下的stopBubble()方法阻止 -->
                </div>
            </li>
        </ul>
    </div>

<script>
    function eventHandle(e){     //不是所有的事件都能冒泡,例如以下事件就不可以冒泡:blur、focus、load、unload
        e = e || window.event;  //獲取事件物件(相容瀏覽器->IE下的全域性物件window.event和其他瀏覽器下的事件物件e;因為IE中沒有e這個事件物件)
        var obj = e.target || e.srcElement;  //找到發生本次事件的源(相容瀏覽器->IE下的e.srcElement以及其他瀏覽器下的e.target
console.log(obj.id + ' was click'); } function showNum(data){ console.log(data); } function showNumStop(e,data){ console.log(data); stopBubble(e); //呼叫函式 } function stopBubble(e){ e = e || window.event; if(e.stopPropagation){ e.stopPropagation(); //非IE瀏覽器取消事件冒泡 console.log('已經阻止事件向上冒泡'); }else{ e.cancelBubble = true; //IE瀏覽器取消事件冒泡 console.log('已經阻止事件向上冒泡'); } } function notTurnToHerf(e){ //取消事件的預設行為,比如取消<a href="">的跳轉行為 e = e || window.event; if (e.preventDefault) { e.preventDefault(); //非IE瀏覽器取消事件預設行為 console.log('已經阻止事件a的預設跳轉行為'); } else { e.returnValue = false; //IE瀏覽器取消事件預設行為;注意:不可用return false代替的,return false只能取消元素 console.log('已經阻止事件a的預設跳轉行為'); } } </script> </body> </html>