Analysis of Event Bubbling and Event Capture in js

  • 2021-11-13 00:47:31
  • OfStack

Directory 01-Event Bubble 1.1-Event bubble introduction
1.2-Event Bubble Exploitation (Event Delegation)
1.3-Event bubbling affects and prevents event bubbling
02-Event capture 1.1-Introduction to Event Capture
1.2-Event 3 Stages

01-Event bubbling

1.1-Event bubble introduction

Knowledge points in this section: introduce what event bubbling is

Event bubbling: If an event for an element is triggered, events of the same name for all of its parent elements will be triggered in turn

Element- > Parent element- > body- > html- > document- > window

Event Bubble 1 exists, but we didn't add an event with the same name to the parent element before


<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> Event bubbling </title>
    <style>
        .parent {
            position: relative;

            width: 200px;
            height: 200px;
            background-color: pink;
        }

        .son {
            position: absolute;

            left: 400px;
            top: 300px;

            width: 100px;
            height: 100px;
            background-color: red;
        }
    </style>
</head>

<body>
    <!--  Bubble : bubble -->

    <div class="parent">
        <div class="son"></div>
    </div>

    <script>
        //  Proof bubbling :  Add the same type of event to father and son 

        const parent = document.querySelector('.parent')
        const son = parent.firstElementChild

        //  Bind a parent-child click event 
        parent.onclick = function () {
            console.log('parent')
        }

        //  Click parent Elements:   Output parent ,   Click son Elements:   Also output parent
        // 1.  Events are common to all elements:   Give or not give events,   Have both 
        // 2.  Click son Triggered parent Click events of:   Event bubbling occurs 

        //  All elements have events,   Include top-level objects window
        window.onclick = function () {
            console.log('window')
        }

        //  Event chain:   Target element - "Superior - "Superior - " body- " html- " document- " window
        //  Event bubbling:   Most of the time it doesn't work (and it's bad) 
    </script>
</body>

</html>

1.2-Event Bubble Exploitation (Event Delegation)

Knowledge points in this section: Introduce the benefits of event bubbling

Event bubbling benefits: If you want to add events to multiple children of the parent element, you can just add events to the parent element, and then

By getting the event source (e. target), you can know which 1 child element triggered this event


<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件冒泡 - 应用 - 事件委托</title>
    <style>
        li {
            margin: 20px 0;
        }
    </style>
</head>

<body>
    <ul>
        <li>百里守约1</li>
        <li>百里守约2</li>
        <li>百里守约3</li>
    </ul>

    <script>
        // 需求: 给所有li增加鼠标的移入移出事件: 变色即可
        // document.querySelectorAll('li').forEach(function (li) {
        //     li.onmouseover = function () {
        //         this.style.backgroundColor = 'red'
        //     }

        //     li.onmouseout = function () {
        //         this.style.backgroundColor = ''
        //     }
        // })

        // 1. 代码的执行效率偏低: 需要给所有的li,1个1个的绑定事件
        // 2. 可扩展性弱: 新增1个li,将会无效
        // innerHTML: 所有都无效
        // document.querySelector('ul').innerHTML += '<li>innerHTML的li</li>'
        // 逻辑: 取出ul中的所有li(结构,不包含事件), 再放进去(字符串形式): 所有的事件全部丢失

        // document.createElement() + appendChild(): 新增的无效
        // let li = document.createElement('li')
        // li.innerHTML = 'creatElement创建的li'
        // document.querySelector('ul').appendChild(li)

        // 事件委托: 将子元素该绑定的事件(效果代码) 绑定到父元素身上
        document.querySelector('ul').onmouseover = function (e) {
            // 事件对象中: e.target 是触发事件的原始目标(最上面的孩子)
            console.log(e.target)

            // 如何区分目标元素是li还是ul呢? 节点: 节点3要素
            // nodeType: li和ul都是元素,   1
            // nodeValue: li和元素都是元素, null
            // nodeName: 是元素标签名字的大写: LI UL
            console.log(e.target.nodeName)
            if (e.target.nodeName === 'LI') {
                // 是目标元素
                e.target.style.backgroundColor = 'red'
            }
        }

        document.querySelector('ul').onmouseout = function (e) {
            if (e.target.nodeName === 'LI') {
                // 是目标元素
                e.target.style.backgroundColor = ''
            }
        }

        // 最大的优点: 事件绑定1次(性能极大提升)
        // 次要优点: 不论是innerHTMl的修改还是createElement的创建: 所有的li都有效
        // document.querySelector('ul').innerHTML += '<li>innerHTML的li</li>'
        // 正是因为有了事件委托: 以后不用再使用创建元素,直接使用innerHTML方便太多

        // let li = document.createElement('li')
        // li.innerHTML = 'creatElement创建的li'
        // document.querySelector('ul').appendChild(li)

        // 事件委托: 是事件冒泡唯1的价值(挺有用)
    </script>
</body>

</html>

1.3-Event bubbling affects and prevents event bubbling

Knowledge points in this section: Introduce the impact of event bubbling

Event bubbling can lead to conflicting requirements: For example, if I want to add a function, click the blank area of body after popping up the login window to make the login window disappear
At this time, the a tab pop-up login window click event will trigger the body click event, causing the login window 1 to disappear when it comes out

Solution: Prevent events from bubbling (knowledge points in the next section)

Knowledge point in this section: Prevent events from bubbling

Prevent event bubbling: Keep events with the same name from bubbling (triggering) in the parent element


 *  Speak human words: click 1 Elements only fire the event of the current element, not the event of the parent element with the same name 

Syntax: Event Object. Not supported before stopPropagation () IE 8

Event Object. Support before cancelBubble = true IE8

Note: If you want to prevent the event from bubbling, 1 must receive the event object in the function that triggers the event


<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> Event bubbling  -  Influence  -  Prevent events from bubbling </title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        a {
            text-decoration: none;
            display: block;

            width: 200px;
            margin: 20px auto;
        }

        .form {
            position: relative;

            width: 400px;
            height: 200px;
            margin: 0 auto;
            text-align: center;
            border: 1px solid #ccc;

            display: none;
        }

        .form span {
            display: block;
            position: absolute;
            right: -25px;
            top: -25px;

            width: 50px;
            height: 50px;
            text-align: center;
            line-height: 50px;
            border: 1px solid #ccc;
            border-radius: 50%;
            background-color: #fff;
            cursor: pointer;

        }
    </style>
</head>

<body>
    <a href="javascript:;" rel="external nofollow" > Click me to display the login box </a>

    <div class="form">
        <span>X</span>
         User name : <input type="text" name="username"><br>
         Password : <input type="password" name="password"><br>
        <button> Login </button>
    </div>

    <script>
        //  Event bubbling :  Child element event trigger ,  Causes the same parent element event to be triggered 

        //  Demand :  Click   Link   Show login box ,  Click on any blank space ,  Hide the login box 
        const a = document.querySelector('a')
        const form = document.querySelector('.form')
        const x = form.firstElementChild

        //  Prevent bubbling :  Block the delivery of events :  Event object e.stopPropagation()
        //  Child element if you do not want the parent element to trigger the same event as the child element :  In the event of a child element , Block delivery 

        // 1.  To a Do click events :  Display div.form
        a.onclick = function (e) {
            console.log('a')
            form.style.display = 'block'

            console.log(e)
            //  Block delivery :  Click event ,  To a End here 
            e.stopPropagation()
        }

        // 2.  Click Blank to hide div.form:  Simple :  To document || window Do click events 
        document.onclick = function () {
            console.log('document')
            form.style.display = ''
        }

        // 3.  For the sake of safety :  Let the whole formdiv You can click on it ,  Will not be passed 
        form.onclick = function (e) {
            e.stopPropagation()
        }

        // 4.  Click Close 
        x.onclick = function () {
            form.style.display = ''
        }

        //  Summarize 
        //  In actual development :  It is possible that father and son have the same type of events ,  If the effect is the opposite (a To display div,document To hide div),1 It is generally used to prevent event delivery : e.stopPropagation()
    </script>
</body>

</html>

02-Event capture

1.1-Introduction to Event Capture

Knowledge point in this section: Event capture

1. Event bubbling: From the trigger event element, find the parent element from level 1 to level 1 to trigger the event with the same name. If there is one, it will be triggered 2. Event capture: Find the child element from the top-level parent element level 1 and level 1 to trigger the event with the same name until the element that triggered the event

Event capture and event bubbling trigger events in the opposite order

3. Event capture, only through addEventListener and parameter writing true is event capture

Everything else is bubbling (not added through addEventListener, the addEventListener parameter is false)

4. Event Object. stopPropagation () prevents capture as well as bubbling 5. IE8 and not captured before!

1.2-Event 3 Stages

Knowledge points in this section: introduce the three stages of the event

1. Event 1 has three phases: Event execution sequence

1Capture phase:
2 Target phase:
3 bubbling stage:

2. Event Object. eventPhase can obtain which stage is triggered when this event is triggered 3. Capture from the top level down to level 1, then capture the target, bubble the target, and then bubble up to level 1

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> Event capture </title>
</head>

<body>
    <div class="box"> I'm Mark </div>

    <script>
        // on Events :  It's all bubbling events 

        window.onclick = function () {
            console.log('window Bubbling event of ')
        }

        document.onclick = function () {
            console.log('document Bubbling event of ')
        }

        const box = document.querySelector('.box')

        box.onclick = function () {
            console.log('box Bubbling event of ')
        }

        //  Capture event : Only 1 A kind of way  addEventListener(' Event type ', Callback function ,true)
        window.addEventListener('click', function () {
            // console.log('window Capture event of ')
        }, true)

        document.addEventListener('click', function () {
            console.log('document Capture event of ')
        }, true)

        //  Event captured only 1 Value :  Prepare for the event target 

        //  Event flow :  Capture first    Post-target    Re-bubbling 
        //  Target phase :  Do not distinguish between capture and bubbling ( Which code comes first , Which executes first )
        //  The latest Google :  Capture first and then bubble 
        // IE Is in order ( Target phase )

        // box There has been a little click bubbling in front 
        box.addEventListener('click', function () {
            console.log('box Capture event of ')
        }, true)

        // e.stopPropagation()  Organize event delivery:   If you block it during the capture phase :  Cause js Out bug
        window.addEventListener('click', function (e) {
            e.stopPropagation()
        }, true)

    </script>
</body>

</html>```

Related articles: