Javascript 冒泡、捕獲、事件代理

2019開工荒了兩天,趕緊開始!

爲什麼寫事件代理、冒泡、捕獲,首先冒泡和捕獲是js事件的核心基礎,事件代理原理來自冒泡和捕獲。

此文章略過標準瀏覽器和非標準瀏覽器的事件流講解,原因很簡單我們現在已經幸福了,已經不考慮IE6、7、8了

直接說現代瀏覽器事件流,用兩張圖看看什麼是冒泡 什麼是捕獲,其實從字面意思大概能看出 一個是向外一個是向內。

事件冒泡

事件捕獲

標準事件流

1、捕獲階段 (先從最外層向內查找)
2、目標階段(找到事件元(當前點擊的dom))
3、冒泡階段(向上冒泡傳遞事件)

事件冒泡

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>冒泡</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    
    div {
        padding: 30px;
    }
    
    .div1 {
        background: red
    }
    
    .div2 {
        background: blueviolet
    }
    
    .div3 {
        background: yellowgreen
    }
</style>

<body>
    <div class="div1">
        父
        <div class="div2">
            子
            <div class="div3">
                孫
            </div>
        </div>
    </div>
    <script>
       // javascript事件綁定addEventListener接收三個參數,
       //  1、事件名稱字符串且不帶on
       //  2、回調函數
       //  3、事件流方式(默認爲冒泡(false),捕獲爲true)
        window.onload = function() {
            document.querySelector('.div1').addEventListener('click', function() {
                console.log('點擊div1')
            }, false)
            document.querySelector('.div2').addEventListener('click', function() {
                console.log('點擊div2')
            }, false)
            document.querySelector('.div3').addEventListener('click', function() {
                console.log('點擊div3')
            }, false)
        }
    </script>
</body>

</html>

先演示下冒泡
事件冒泡

事件捕獲

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>冒泡</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    
    div {
        padding: 30px;
    }
    
    .div1 {
        background: red
    }
    
    .div2 {
        background: blueviolet
    }
    
    .div3 {
        background: yellowgreen
    }
</style>

<body>
    <div class="div1">
        父
        <div class="div2">
            子
            <div class="div3">
                孫
            </div>
        </div>
    </div>
    <script>
        window.onload = function() {
            document.querySelector('.div1').addEventListener('click', function(e) {
                console.log('點擊父元素')
            }, true)
            document.querySelector('.div2').addEventListener('click', function(e) {
                console.log('點擊子元素')
            }, true)
            document.querySelector('.div3').addEventListener('click', function(e) {
                console.log('點擊孫子元素')
            }, true)
        }
    </script>
</body>

</html>

看看效果
事件捕獲

事件委託

我理解的事件委託的好處有兩點
1、減少事件綁定次數
2、可以給未知元素綁定事件(例如動態渲染的List)

其原理就是利用事件冒泡向外傳遞的特性,下面代碼解析一下:
同樣忽略低版本瀏覽器獲取當前target兼容性問題

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>冒泡</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    
    div {
        padding: 30px;
        border: 1px solid red
    }
    
    div span {
        display: inline-block;
        padding: 10px;
        border: 1px solid blueviolet
    }
</style>

<body>
    <div class="div1">
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
    </div>
    <script>
        window.onload = function() {
            document.querySelector('.div1').addEventListener('click', function(e) {
                //回調函數e爲事件對象,同夥事件對象可以獲取當前點擊dom
                console.log(e.target)
                //獲取到當前事件源(dom)後再去搞一些你想搞的事情就ok了

                //搞事情代碼
            }, false)

        }
    </script>
</body>

</html>

老規矩,看看效果
事件委託

最後順便說一下事件對象功能很全的,看下圖能獲取到很多當前dom的周邊,可以搞好多其它的事情。
事件對象

感謝閱讀,歡迎吐槽!謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章