js event and event delegation

Posted by birdie on Sat, 19 Feb 2022 00:52:55 +0100

1. Events

When users browse web pages, there are many operations that interact with web pages. For example, click the button, slide the screen, move the mouse, etc. through these interactions, some operations can be completed to achieve some effect. We can call these interactions events.

2. Event bubbling

Event bubbling refers to the event propagating upward (parent element) to document after being triggered on an element. Triggered if the same event is encountered in the process of bubbling up. For example, the following example:

<body>
    <div id="myDiv">
        <ul>
            <li id="myLi">1</li>
        </ul>
    </div>
    <script>
        const li = document.getElementById('myLi')
        li.onclick = function () {
            console.log(this.id); //myLi
        }

        const div = document.getElementById('myDiv')
        div.addEventListener('click', function () {
            console.log(this.id); //myDiv
        })
    </script>
</body>


When we click the li tag, the click event bound to li will be triggered, but after the click event of li is triggered, the click event bound to div will be triggered. This is the event bubble. In fact, it is understandable to think about it carefully, because clicking the li tag means that the div is also clicked. Just like you live in a province in China, you must live in China. The total foaming process is as follows:

li >ul > div >body >html >document

3. Event capture

Event capture and event bubbling are exactly the opposite process. Event capture starts from document and then propagates down once to know the specific elements

//dom2 event handlers can control event capture and event bubbling
//And only when the third parameter of addEventListener is set to true can it be event capture, and false is event bubbling.
const lis = document.getElementsByTagName('li')
for (const li of lis) {
	li.addEventListener('click', () => {
		console.log('li click');
	}, true)
}

const div = document.getElementById('myDiv')
div.addEventListener('click', () => {
	console.log('div click');
}, true)


It can be seen that event capture is indeed the opposite of event bubbling. Event capture executes the click event of div first, and then the click event of li. The order of capture is as follows

document >html >body >div >ul >li

4. Event model

4.1 DOM0 event model

The DOM0 event model is relatively simple. You only need to assign an event handler function to an event handler attribute. All current browsers support this method.

const div = document.getElementById('myDiv')
div.onclick = function () {
    console.log(this.id) // myDiv
}

Remove the event mode from the DOM0 event model and directly set the value of the event handler property to null

div.onclick = null

4.2 DOM2 event model

The DOM2 event model defines two methods for the assignment and removal of event handlers: addEventListener() and removeEventListener(). They receive three parameters: event name, event handler function and Boolean value (false by default). true indicates that the event handler is called in the capture phase and false indicates that the event handler is called in the bubble phase.

const div = document.getElementById('myDiv')
const handler = function () {
	console.log(this.id);
}
// Bind click event
div.addEventListener('click', handler)

// Remove click event
div.removeEventListener('click', handler)
// Bind click event
div.addEventListener('click', function () {
	console.log(this.id);
})

// Cannot remove click event
div.removeEventListener('click', function () {
	console.log(this.id);
})

tip: the event handling functions passed to addEventListener and removeEventListener must be assigned to a variable before they can be used together to remove the bound event. Otherwise, the bound event cannot be removed. Because when it cannot be removed, although the event handling function looks the same, it is actually two different functions with different memory addresses.

4.3 IE event model

Ie event model defines two methods for the assignment and removal of event handlers: attachEvent() and attachEvent(). They receive two parameters: event name and event handler function. Because IE8 and earlier versions only support event bubbling, event handlers added using attachEvent() are added to the bubbling phase.

const div = document.getElementById('myDiv')
const handler = function () {
	console.log(this.id);
}

//Add a click event. Note onClick
div.attachEvent("onclick", handler);

//Remove event
div.detachEvent("onclick", handler);

4.4 other matters of the three event models

this points to the current element in the DOM0 event

In the DOM0 event, onclick is assigned to the same element twice, and the previous one will be overwritten later (because it is assigned)

this points to the current element in the DOM2 event

DOM2 can add multiple event functions for the same element through addEventListener and execute them sequentially (observer mode)

In IE event model, the event handler runs in the global scope, so this is equal to window

IE event model can add multiple event functions for the same element through attachEvent, but it is executed in reverse order, that is, the one added first and executed last

5. Event delegation

Event delegation is also called event proxy. Event delegation is to delegate the event originally bound to the child element to the parent element. The most common in development is that the menu bar is composed of ul and multiple sub li tags. If you want to add a click event to the menu bar, the usual method is to bind the corresponding click event directly to the li. However, this is not conducive to adding other menu items in the future, that is, the so-called scalability. And adding events to each li is time-consuming and laborious. Therefore, the usual solution is to use the feature of event bubbling to bind the event to the ul tag.

A popular example is that in the dormitory, everyone had to pick up the express, but it was a waste of manpower, so we democratically chose the head of the dormitory to go alone and receive it together.

Here's a practical example:

<body>
    <ul id="myUl">
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        //Event delegate implementation
        const ul = document.getElementById('myUl')
        ul.onclick = function (e) {
            console.log(e.target.innerHTML);
        }

		//Equivalent code of event delegate: add an event for each li,
        const lis = document.getElementsByTagName('li')
        for (const li of lis) {
            li.onclick = function () {
                console.log(this.innerHTML);
            }
        }
    </script>
</body>


The event delegate can obtain the clicked target from the target attribute of the event object. It can be seen that using the event delegate, you only need to bind the required event on the parent element. Through general event binding, you need to bind events for each child element.

Advantages of event delegation:

By using event delegation, you do not need to set event functions for each child element, which can reduce the memory required by the page and improve the overall performance of the page; Realize the dynamic binding of events. The new node does not need to add listening events separately. The events that occur are handed over to the parent element.

Topics: Javascript