A brief analysis of event bubbling and event capture in js

A brief analysis of event bubbling and event capture in js

01-Event Bubbling

1.1- Introduction to event bubbling

Knowledge points in this section: Introduce what event bubbling is

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

element->parent element->body->html->document->window

Event bubbling has always existed, but we didn't add the same event to the parent element before

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

<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>
        // Prove bubbling: Just add the same type of event to the parent and child const parent = document.querySelector('.parent')
        const son = parent.firstElementChild

        // Bind click events to parent and child parent.onclick = function () {
            console.log('parent')
        }

        // Click on the parent element: output parent, click on the son element: also output parent
        // 1. All elements have events: whether they are given events or not, they all have events // 2. Clicking on son triggers the click event of parent: event bubbling occurs // All elements have events, including the top-level object window
        window.onclick = function () {
            console.log('window')
        }

        // Event chain: target element -> parent -> parent -> body -> html -> document -> window
        // Event bubbling: most of the time useless (and bad)
    </script>
</body>

</html>

1.2-Event Bubbling Utilization (Event Delegation)

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

​ Event bubbling benefits: If we want to add events to multiple child elements of a parent element, we only need to add events to the parent element, and then

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

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

<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 - Application - Event Delegation</title>
    <style>
        li {
            margin: 20px 0;
        }
    </style>
</head>

<body>
    <ul>
        <li>Baili Shouyue 1</li>
        <li>Baili Shouyue 2</li>
        <li>Baili Shouyue 3</li>
    </ul>

    <script>
        // Requirement: Add mouse in and out events to all li: just change the color// document.querySelectorAll('li').forEach(function (li) {
        // li.onmouseover = function () {
        // this.style.backgroundColor = 'red'
        // }

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

        // 1. The code execution efficiency is low: all li need to be bound to events one by one // 2. Weak scalability: adding a new li will be invalid // innerHTML: all are invalid // document.querySelector('ul').innerHTML += '<li>innerHTML的li</li>'
        // Logic: Take out all li (structure, excluding events) in ul, and put them back in (string form): All events are lost // document.createElement() + appendChild(): New events are invalid // let li = document.createElement('li')
        // li.innerHTML = 'li created by creatElement'
        // document.querySelector('ul').appendChild(li)

        // Event delegation: Bind the child element's bound event (effect code) to the parent element document.querySelector('ul').onmouseover = function (e) {
            // In the event object: e.target is the original target that triggered the event (the topmost child)
            console.log(e.target)

            // How to distinguish whether the target element is li or ul? Node: Three elements of a node // nodeType: li and ul are both elements, 1
            // nodeValue: li and element are both elements, null
            // nodeName: is the uppercase name of the element tag: LI UL
            console.log(e.target.nodeName)
            if (e.target.nodeName === 'LI') {
                // is the target element e.target.style.backgroundColor = 'red'
            }
        }

        document.querySelector('ul').onmouseout = function (e) {
            if (e.target.nodeName === 'LI') {
                // is the target element e.target.style.backgroundColor = ''
            }
        }

        // Biggest advantage: Event binding once (greatly improved performance)
        // Secondary advantage: Regardless of whether innerHTMl is modified or created by createElement: all li are valid // document.querySelector('ul').innerHTML += '<li>innerHTML的li</li>'
        // It is precisely because of event delegation: there is no need to create elements in the future, it is much more convenient to use innerHTML directly // let li = document.createElement('li')
        // li.innerHTML = 'li created by creatElement'
        // document.querySelector('ul').appendChild(li)

        // Event delegation: is the only value of event bubbling (very useful)
    </script>
</body>

</html>

1.3-Event bubbling influence and prevention of event bubbling

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

Event bubbling can lead to demand conflicts: for example, if I want to add a function, after the login window pops up, click the blank area of ​​the body to make the login window disappear. At this time, the click event of the pop-up login window of the a tag will trigger the click event of the body, causing the login window to disappear as soon as it appears.

Solution: Prevent event bubbling (knowledge point in the next section)

  • Knowledge point of this section: Prevent event bubbling

Prevent event bubbling: prevent events of the same name from bubbling (triggering) in parent elements

 * In layman's terms: Clicking an element will only trigger the event of the current element, not the event of the parent element with the same name

Syntax: event object.stopPropagation() Not supported by IE8 and earlier

Event object.cancelBubble = true Supported before IE8

Note: If you want to prevent event bubbling, be sure to receive the event object in the function that triggers the event

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

<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 - Impact - Preventing Event 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>
        Username: <input type="text" name="username"><br>
        Password: <input type="password" name="password"><br>
        <button>Login</button>
    </div>

    <script>
        // Event bubbling: The child element event triggers, causing the same event of the parent element to be triggered // Requirement: Click the link to display the login box, and click any blank space to hide the login box const a = document.querySelector('a')
        const form = document.querySelector('.form')
        const x = form.firstElementChild

        // Stop bubbling: Stop the event from being passed: event object e.stopPropagation()
        // If the child element does not want the parent element to trigger the same event as the child element: In the child element's event, prevent the transmission // 1. Give a click event: Display div.form
        a.onclick = function (e) {
            console.log('a')
            form.style.display = 'block'

            console.log(e)
            // Prevent transmission: click event, end at a e.stopPropagation()
        }

        // 2. Click on a blank to hide div.form: Simple: give document || window a click event document.onclick = function () {
            console.log('document')
            form.style.display = ''
        }

        // 3. For safety: make the entire formdiv clickable, and do not pass form.onclick = function (e) {
            e.stopPropagation()
        }

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

        // Summary // In actual development: The same type of events may occur in the parent and child. If the effects are opposite (a wants to display div, document wants to hide div), it is generally used to prevent event transmission: e.stopPropagation()
    </script>
</body>

</html>

02-Event Capture

1.1- Introduction to event capture

Knowledge point of this section: event capture

  • 1. Event bubbling: From the element that triggers the event, search for the parent element that triggers the event with the same name one level at a time, and trigger it if there is one
  • 2. Event capture: From the top parent element, search down one level at a time to find the child elements that trigger the event with the same name until the element that triggers the event is found.

Event capture and event bubbling trigger events in the exact opposite order

  • 3. Event capture can only be done through addEventListener and the parameter is written as true

Others are bubbling (not added through addEventListener, addEventListener parameter is false)

  • 4. Event object.stopPropagation() can not only stop bubbling but also stop capturing
  • 5. IE8 and earlier are not captured!

1.2-Three stages of the event

Knowledge points in this section: Introduce the three stages of events

  • 1. There are three stages in an event: the order in which the event is executed

1 – Capture Phase:
2 – Target Phase:
3 – Bubbling Phase:

  • 2. Event object.eventPhase can get the phase when this event is triggered
  • 3. First, capture from the top level downwards, then capture the target, bubble the target, and then bubble up level by level.
<!DOCTYPE html>
<html lang="en">

<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 am Xiao Ma Ge</div>

    <script>
        // on event: all are bubbling events window.onclick = function () {
            console.log('window bubbling event')
        }

        document.onclick = function () {
            console.log('document's bubbling event')
        }

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

        box.onclick = function () {
            console.log('box's bubbling event')
        }

        // Capture events: There is only one way addEventListener('event type', callback function, true)
        window.addEventListener('click', function () {
            // console.log('window capture event')
        }, true)

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

        // The only value of event capture: prepare for the event target // Event flow: capture first, then target, then bubble // Target phase: does not distinguish between capture and bubble (which code is in front, which one is executed first)
        // Latest Google: capture first, then bubble // IE is in order (target phase)

        // There is already a click bubble in front of the box box.addEventListener('click', function () {
            console.log('box capture event')
        }, true)

        // e.stopPropagation() organizes event delivery: If it is blocked in the capture phase: it will cause js bug
        window.addEventListener('click', function (e) {
            e.stopPropagation()
        }, true)

    </script>
</body>

</html>```

This is the end of this article about the brief analysis of event bubbling and event capture in js. For more relevant js event bubbling and event capture content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Learn more about the most commonly used JavaScript events
  • Analysis of JavaScript's event loop mechanism
  • JavaScript event capture bubbling and capture details
  • Detailed explanation of js event delegation
  • JavaScript event loop case study
  • Detailed explanation of Javascript event capture and bubbling methods

<<:  MySQL uses limit to implement paging example method

>>:  How to solve the problem that the project in eclipse cannot be added to tomcat

Recommend

Is the tag li a block-level element?

Why can it set the height, but unlike elements lik...

Pure CSS to achieve click to expand and read the full text function

Note When developing an article display list inte...

Detailed explanation of CSS margin overlap and solution exploration

I recently reviewed some CSS-related knowledge po...

Web designers should optimize web pages from three aspects

<br />With the increase of bandwidth, there ...

Detailed explanation of the properties and functions of Vuex

Table of contents What is Vuex? Five properties o...

How to set focus on HTML elements

Copy code The code is as follows: <body <fo...

Solution to running out of MySQL's auto-increment ID (primary key)

There are many types of auto-increment IDs used i...

Vant+postcss-pxtorem implements browser adaptation function

Rem layout adaptation The styles in Vant use px a...

Methods of adaptive web design (good access experience on mobile phones)

1. Add the viewport tag to the HTML header. At th...

Vite2.0 Pitfalls

Table of contents Vite project build optimization...

Troubleshooting of master-slave delay issues when upgrading MySQL 5.6 to 5.7

Recently, when upgrading the Zabbix database from...

Thirty HTML coding guidelines for beginners

1. Always close HTML tags In the source code of p...

Detailed explanation of the implementation of MySQL auto-increment primary key

Table of contents 1. Where is the self-incremente...