Event Model of JS Project

Keywords: Javascript IE less

There are 1960 words in this article. It takes only 8 minutes to finish reading.

Event

Users interact with web pages through events. Events were initially used as a means of sharing server load. At first, there was no uniform specification. Until DOM2 level, Netscape and IE began to have their own API specifications.

For the triggering mechanism of events, both companies believe that the triggering mechanism of pages is not just clicking on an element, but triggering the event of the current target element.

For example, the page has many concentric circles. When you click on the innermost circle, you actually click on the circles that contain the outside of the circle. The two companies agree on this point, but they adopt two different schemes in the sequence of event flow transmission, namely event bubbling and event capture.

I. Event Bubble

IE browser has been supporting event bubbling mechanism since the old version. The so-called event bubbling refers to the event flow is received from more specific elements, and has been disseminating non-specific elements.

It is propagating from the target element to the parent element.

<body>
    <div id="parent">
        <div id="child"></div>
    </div>
    <script>
    function childEventHandler(event) {
        console.log(this);
        console.log("child Clicked");
    }
    function parentEventHandler(event) {
        console.log(this);
        console.log("parent Clicked");
    }
    function bodyEventHandler(event) {
        console.log(this);
        console.log("body Clicked");
    }
    function htmlEventHandler(event) {
        console.log(this);
        console.log("html Clicked");
    }
    function documentEventHandler(event) {
        console.log(this);
        console.log("document Clicked");
    }
    function windowEventHandler(event) {
        console.log(this);
        console.log("window Clicked");
    }
    var bodyEl = document.getElementsByTagName("body")[0];
    var htmlEl = document.getElementsByTagName("html")[0];
    var win = window;
    var parentEl = document.getElementById("parent");
    var childEl = document.getElementById("child");
    childEl.onclick = childEventHandler;
    parentEl.onclick = parentEventHandler;
    bodyEl.onclick = bodyEventHandler;
    htmlEl.onclick = htmlEventHandler;
    document.onclick = documentEventHandler;
    win.onclick = windowEventHandler;
    </script>
</body>

As shown in the figure below, if you click on the element whose id is child, the event flow propagates from child to window object.

All modern browsers support event bubbles.

II. Event capture

Event capture led by Netscape is just the opposite of event bubbles. Event streams start to trigger from non-specific elements and then spread to specific elements. In short, it propagates from the parent element to the target element.

Event capture is supported from IE 9 and is not compatible with older browsers, so fewer people use it.

III. Event Flow

DOM stipulates that events include three stages: event capture, target stage and event bubbling.

Browsers starting with IE 9 stipulate that the sequence of event streams is event capture, event interception, and then in the target stage, the actual target receives the event, and finally event bubbles, which can respond to the event at this stage.

Take the previous child element as an example, until the child element receives the event (from window to parent), it is the event capture phase. When the child element is reached, the event is processed at this time, and then bubbles onto the window object. The bubbling stage can also handle the event. Based on the characteristics of event bubbling, the event delegation mechanism related to event bubbling will be discussed later.

Event Binding

HTML binds to events in three forms:

1. 
<div id="child" onclick="console.log('hello');"></div>

2. 

var childEl = document.getElementById("child");
childEl.onclick = function() {
    console.log('hello');
}

3. 
var childEl = document.getElementById("child");
childEl.addEventListener('click', function() {
    console.log('hello');
}, false);

JavaScript is a single-threaded language. When an element is triggered by an event, it looks for a function bound to the event queue. If not, it does nothing. If it does, it puts the function in front of the event queue and waits for the main thread event to execute after it has been executed.

The first binding of the above code, writing events in html without decoupling performance and behavior, is not recommended.

The second kind of binding, which binds events to element objects, is mainly event-prone coverage.

The third kind of binding, first, the third parameter is Boolean value, default is false, which means calling event handler in event bubbling phase, and if true, it means calling event handler in event capture phase.

When we want to deal with an event, we should bind the event of the element to be empty when we do not want to deal with the event binding of the element, if memory leaks are prone to occur.

The first way of writing is:
childEl.onclick = null;


The third way of writing:
function eventHandler() {
    console.log('hello');
}

childEl.addEventListener('click', eventHandler, false);

childEl.removeEventListener('click', eventHandler, false);

5. Event Delegation (Event Agent)

Event delegation takes advantage of the bubbling nature of events. Event streams are initially received from more specific elements and are always propagated on less specific elements.

First, if there is a list ul, every list element li click triggers an event handler. Obviously, if you bind events to elements one by one, the efficiency is certainly not good.

At the same time, when an element is added, events are unlikely to bind successfully. Together:

<ul id="menu">
    <li class="menu-item">menu-1</li>
    <li class="menu-item">menu-2</li>
    <li class="menu-item">menu-3</li>
    <li class="menu-item">menu-4</li>
</ul>
<input type="button" name="" id="addBtn" value="Add to" />

<script>
window.onload = function() {
        var menu = document.getElementById("menu");
        var item = menu.getElementsByClassName('menu-item');
        for (var i = 0; i < item.length; i++) {
            item[i].onclick = (function(i) {
                return function() {
                    console.log(i);
                }
            }(i))
        }

        var addBtnEl = document.getElementById("addBtn");
        addBtnEl.onclick = function() {
            var newEl = document.createElement('li');
            newEl.innerHTML = "menu-new"
            menu.appendChild(newEl);
        }
    }
</script>

New menu-new, Click to find no response, indicating that the event is not bound in, but we also do not want to add a new element, for this new element binding events, duplicate inefficient work should be avoided.

We think through the idea of event delegation that the target element itself will still have events when events flow propagates, but at the same time, after bubbling out, the higher level dom can also handle the event program. Then, we only need to bind events to high-level nodes, by judging which sub-nodes are triggered, and then do the corresponding event processing.

<ul id="menu">
    <li class="menu-item">menu-1</li>
    <li class="menu-item">menu-2</li>
    <li class="menu-item">menu-3</li>
    <li class="menu-item">menu-4</li>
</ul>
<input type="button" name="" id="addBtn" value="Add to" />

<script>
window.onload = function() {
        var menu = document.getElementById("menu");
        menu.onclick = function(event) {
            var e = event || window.event;
            var target = e.target || e.srcElement;
            console.log(e);
            switch (target.textContent) {
                case "menu-1":
                    console.log("menu-1 Clicked");
                    break;

                case "menu-2":
                    console.log("menu-2 Clicked");
                    break;

                case "menu-3":
                    console.log("menu-3 Clicked");
                    break;

                case "menu-4":
                    console.log("menu-4 Clicked");
                    break;

                case "menu-new":
                    console.log("menu-new Clicked");
                    break;
            }
        }

        var addBtnEl = document.getElementById("addBtn");
        addBtnEl.onclick = function() {
            var newEl = document.createElement('li');
            newEl.innerHTML = "menu-new"
            menu.appendChild(newEl);
        }
    }
</script>

Every submenu element in the menu list responds to events correctly, and the newly added menu-new also responds to events correctly.

The advantage of event delegation is that we don't have to manually add binding events to each element to avoid duplicating inefficient work.

Secondly, event delegation can get less dom and initialize element objects and event functions, which can effectively reduce memory usage.

Whenever an event program is assigned to an element, a connection is established between html code and js code. The more such connections, the slower the page will execute. Event delegation can effectively reduce the connection tree and improve the performance of the page.

summary

The interaction between users and web pages is through events. Event models are divided into event bubbles and event capture. Event bubbles are more compatible and widely used. Event delegation can be established to improve the performance of web pages through event bubbles.

Posted by rhysmeister on Thu, 09 May 2019 08:46:38 -0700