Home > Web Front-end > JS Tutorial > body text

Techniques for writing performance-efficient JavaScript events_javascript tips

WBOY
Release: 2016-05-16 16:29:46
Original
1273 people have browsed it

How to create an efficient web front-end program is a question I unconsciously consider every time I do front-end development. A few years ago, the awesome front-end engineers at Yahoo published a book on improving web front-end performance, which caused a sensation in the entire web development technology community. The mysterious web front-end optimization problem became a common problem on the street, and web front-end optimization became Simple questions that both rookies and experts can answer. When the entire industry knows the shocking secret answer, then the existing optimization technology can no longer produce a qualitative leap in the website you develop. In order to make the website we develop perform better than others To make our website better, we need to think more deeply independently and reserve better skills.

The event system in Javascript is the first breakthrough point that comes to my mind. Why is it a JavaScript event system? We all know that the web front-end includes three technologies: html, css and javascript. It is very clear how html and css are combined: style, class, id and html tags. There is not much to say about this, but how does javascript get into the middle of html and css? , how about integrating the three? Finally, I found that this entry point is the event system of JavaScript. No matter how long or complex the JavaScript code we write, it will eventually be reflected in HTML and CSS through the event system. So I was thinking that since the event system is the entry point for the integration of the three point, then there will inevitably be a large number of event operations in a page, especially in today's increasingly complex web pages. Without these events, our carefully written javascript code will only be stored in the database, and the hero will be useless. Since there will be a large number of event functions on the page, will there be any problems affecting efficiency if we write event functions according to our habits? The answer I have researched is that there is a real efficiency problem, and it is also a serious efficiency problem.

In order to explain my answer clearly, I need to first explain the JavaScript event system in detail.

The event system is the entry point for the integration of javascript, html and css. This entry point is like the main function in java. All magic starts from here. So how does the browser complete this entry? I have researched a total of 3 ways, they are:

Method 1: html event processing

HTML event processing is to write the event function directly in the html tag. Because this writing method is tightly coupled with the html tag, it is called html event processing. For example, the following code:

Copy code The code is as follows:

 

If the click event function is complicated, writing the code like this will definitely cause inconvenience, so we often write the function externally, and onclick directly calls the function name, for example:

Copy code The code is as follows:


function btnClk(){
alert("click me!");
}

The above writing method is a very beautiful writing method, so many people still use it unconsciously nowadays, but maybe many people don’t know that the latter writing method is actually not as robust as the former one. This is what I did not long ago. Problems encountered when studying non-blocking loading script technology, because according to the principle of front-end optimization, javascript code is often located at the bottom of the page. When the page is blocked by scripts, the functions referenced in the html tag may not have been executed yet. At this time, When we click the page button, the result will be "XXX function undefined error". In JavaScript, such errors will be captured by try and catch. Therefore, in order to make the code more robust, we will rewrite it as follows:

Copy code The code is as follows:

 

Seeing the above code, I can’t describe how disgusting it is.

Method 2: DOM level 0 event processing

DOM0-level event processing is an event processing supported by all browsers today. There are no compatibility issues. Seeing such a sentence will make everyone who works on the web front-end excited. The rules for DOM0 event processing are: each DOM element has its own event processing attribute, which can be assigned a function, such as the following code:

Copy code The code is as follows:

var btnDOM = document.getElementById("btn");
btnDOM.onclick = function(){
alert("click me!"); }

The event attributes of DOM level 0 event processing are all defined in the form of "on event name", and the entire attribute is in lowercase letters. We know that the DOM element is a javascript object in the javascript code, so it is very easy to understand DOM level 0 event processing from the perspective of javascript objects, such as the following code:

Copy code The code is as follows:
btnDOM.onclick = null; 

Then the button click event is cancelled.

Look at the following code again:

Copy code The code is as follows:
btnDOM.onclick = function(){
alert("click me!"); }

btnDOM.onclick = function(){
alert("click me1111!"); }



The latter function will overwrite the first function.
 

Method three: DOM2 event processing and IE event processing

DOM2 event processing is a standardized event processing solution, but IE browser has developed its own set. The functions are similar to DOM2 event processing, but the code is different.

Before explaining method three, I must add some concepts, otherwise I will not be able to explain the connotation of method three clearly.

The first concept is: event flow

In page development, we often encounter such a situation. The working area of ​​a page can be represented by document in JavaScript. There is a div in the page. The div is equivalent to covering the document element. There is a button element in the div. The button element covers the div, which is also equivalent to covering the document, so the problem is that when we click the button, the click behavior does not only occur on the button, but the click operation is applied to both the div and the document. These three elements of logic can trigger click events, and event flow is the concept that describes the above scenario. Event flow means: the order in which events are received from the page.

The second concept: event bubbling and event capturing

Event bubbling is a solution proposed by Microsoft to solve the event flow problem, while event capture is an event flow solution proposed by Netscape. Their principles are as follows:


The bubbling event starts with the div, followed by the body, and finally the document. The event capture is reversed, with the document first, then the body, and finally the target element div. In comparison, Microsoft's solution is more user-friendly In line with people's operating habits, Netscape's solution is very awkward. This is the consequence of the browser war. Netscape was a step too slow to solve the problem of event flow with code that sacrificed users' habits.

Microsoft has designed a new event system based on bubbling events, which is commonly called IE event processing in the industry. The IE event processing method is as shown in the following code:

Copy code The code is as follows: var btnDOM = document.getElementById("btn");
btnDOM.attachEvent("onclick",function(){
alert("Click Me!");
});



Add events through the attachEvent method of DOM elements under IE. Compared with DOM0 event processing, the way to add events has changed from attributes to methods, so when we add events, we need to pass parameters to the method. The attachEvent method receives two Parameters. The first parameter is the event type. The naming of the event type is the same as the event naming in DOM0 event processing. The second parameter is the event function. The advantage of using this method is that if we are adding a click event to the same element, As shown below:

Copy code The code is as follows: btnDOM.attachEvent("onclick",function(){
alert("Click Me!");
});
btnDOM.attachEvent("onclick",function(){
alert("Click Me,too!");
});

After running, both dialog boxes can pop up normally. This method allows us to add multiple different click events to DOM elements. What if we don’t want an event? What should we do? Internet Explorer provides the detachEvent method for deleting events. The parameter list is the same as that of attachEvent. If we want to delete a click event, we only need to pass the same parameters as the add event, as shown in the following code:

Copy code The code is as follows:

btnDOM.detachEvent("onclick",function(){
alert("Click Me,too!");
});

When we run it, the consequences are very serious. We are very confused. The second click is not deleted. What is going on? I mentioned earlier that deleting events requires the same parameters as adding events, but in the anonymous function of JavaScript, even if the code of the two anonymous functions is exactly the same, JavaScript will use different variables to store it internally. The result is that the phenomenon we see cannot be Delete the click event, so our code should be written like this:

Copy code The code is as follows:

var ftn = function(){
alert("Click Me,too!");
};
btnDOM.attachEvent("onclick",ftn);
btnDOM.detachEvent("onclick",ftn);

The adding method and deleting method point to the same object, so the event is deleted successfully. The scene here tells us that we should have good habits when writing events, that is, the operating functions should be independently defined, and do not use anonymous functions as a habit.

The next step is DOM2 event processing. Its principle is shown in the figure below:

DOM2 is a standardized event. Using DOM2 events, event delivery first starts from the capture method, that is, from the document, to the body. The div is an intermediary point. When the event reaches the intermediary point, the event is in the target stage, and the event enters the target stage. After that, the event starts to bubble up, and finally the event ends on the document. (The starting point of the capture event and the end point of the bubbling event are all pointed to the document. The actual situation is that some browsers will start capturing from the window and end the bubbling. However, I think that no matter how the browser itself is set during development, we Paying attention to document is more meaningful for development, so I always use document here). People are accustomed to classify the target stage as part of bubbling, mainly because bubbling events are more widely used in development.

DOM2 event processing is very troublesome. Every time the event is triggered, all elements will be traversed twice. Compared with IE events, the performance is much worse. IE only bubbles, so IE only needs to traverse once, but the traversal The lack of it does not mean that IE's event system is more efficient. From a development and design perspective, supporting both event systems will bring greater flexibility to our development. From this perspective, DOM2 events are still very promising. The code for the DOM2 event is as follows:

Copy code The code is as follows:

var btnDOM = document.getElementById("btn");
btnDOM.addEventListener("click",function(){
alert("Click Me!");
},false);
var ftn = function(){
alert("Click Me,too!");
};
btnDOM.addEventListener("click",ftn,false);

To add events in DOM2 event processing, addEventListener is used. It receives three parameters and one more than ie event processing. The first two have the same meaning as the two parameters of the ie event processing method. The only difference is the first parameter. The on prefix needs to be removed. The third parameter is a Boolean value. If its value is true, then the event will be processed according to the capture method. If the value is false, the event will be processed according to bubbling. With the third parameter we can Understand why the event element must be run twice in DOM2 event processing. The purpose is to be compatible with the two event models. However, please note here that no matter we choose to capture or bubble, the two traversals will be carried out forever. If we choose One event processing method, then no event processing function will be triggered in another event processing process, which is the same as a car idling in neutral. Through the design of the DOM2 event method, we know that DOM2 events can only execute one of the two event processing methods at runtime. It is impossible for two event stream systems to trigger at the same time. Therefore, although the element is traversed twice, the event function will never It may be triggered twice. Note that when I say not triggered twice, it refers to an event function. In fact, we can simulate the simultaneous execution of two event flow models, such as the following code:

Copy code The code is as follows:

btnDOM.addEventListener("click",ftn,true);
btnDOM.addEventListener("click",ftn,false);

But this way of writing is multi-event processing, which is equivalent to us clicking the button twice.

DOM2 also provides a function to delete events. This function is removeEventListener, which is written as follows:

Copy code The code is as follows:

btnDOM.removeEventListener("click",ftn,false);

Used the same as IE events, that is, the parameters must be consistent with the parameters defining the event. However, when using removeEventListener, the third parameter is not passed. The default is to delete the bubbling event, because if the third parameter is not passed, the default is false. For example:

Copy code The code is as follows:

btnDOM.addEventListener("click",ftn,true);
btnDOM.removeEventListener("click",ftn);

Run it and find that the event was not deleted successfully.

The last thing I want to say is that DOM2 event processing is well supported in ie9, including ie9 and above. DOM2 events are not supported below ie8.

 Let’s compare the three event methods as follows:

 Comparison 1: Method 1 is compared with the other two methods

Method 1 is written by combining HTML and JavaScript. There is me in you and you in me. To deepen this method is the mixed development of HTML and JavaScript. Expressed in a software term, it is code coupling. The code coupling is not good. , and it is very bad. This is the level of a novice programmer, so the first method is completely defeated, and the other two methods are completely defeated.

Comparison 2: Method 2 and Method 3

The two writing methods are similar. Sometimes it is really hard to say which one is better and which one is worse. Looking at the above content, we find that the biggest difference between method two and method three is: when using method two, a DOM element can have a certain event and only once. Method three allows a certain event of a DOM element to have multiple event processing functions. In DOM2 event processing, method three also allows us to precisely control the event flow. Therefore, method three is more powerful than method two, so In comparison, method three is slightly better.

The following is the focus of this article: the performance problem of the event system. To solve the performance problem, we must find a focus. Here I think about the performance issues of the event system from two focus points. They are: reducing the number of traversals and memory consumption.

The first is the number of traversals. Whether it is a capture event stream or a bubbling event stream, the elements will be traversed, but the traversal will start from the top window or document. If the parent-child relationship between the page DOM elements is deep, then the traversal will The more elements there are, like DOM2 event processing, the greater the danger of traversal. How to solve this event stream traversal problem? My answer is no. Some friends here may have questions, how come there is no more? There is an event object in the event system, which is event. This object has methods to prevent bubbling or capturing events. How can I say it doesn't? This friend's question is very reasonable, but if we want to use this method to reduce traversal, then our code must deal with the relationship between parent and child elements, and the relationship between grandfather and grandson elements. If there are many nested elements on the page, this is an impossible task. So my answer is that you can't change the traversal problem, you can only adapt to it.

It seems that reducing traversals cannot solve the event system performance problem, so now the only consideration is memory consumption. I often hear people say that C# is easy to use, but it is even better for web front-end development. We can directly drag a button to the page in the C# IDE. After the button reaches the page, the javascript code will automatically add an event to the button. Of course The event function inside is an empty function, so I thought we could place 100 buttons on the page in this way. Without even a single code, we would have 100 button event handlers, which is super convenient. Finally, we added a specific button to one of the buttons. Events allow the page to run. Is this page efficient? In JavaScript, each function is an object, and each object consumes memory, so these useless 99 event function codes must consume a lot of precious browser memory. Of course we wouldn't do this in a real development environment, but in today's era when ajax is popular and single-page development is crazy popular, there are so many events on a web page, which means that each of our events has an event function. But each operation we perform will only trigger one event. At this time, other events are lying down and sleeping, which has no effect and consumes the computer's memory.

We need a solution to change this situation, and there is indeed such a solution in reality. In order to clearly describe this solution, I need to add some background knowledge first. When describing DOM2 event processing, I mentioned the concept of target object. Putting aside the DOM2 event processing method, there is also the concept of target object in capture event processing and bubbling event processing. , the target object is the DOM element of the specific operation of the event. For example, in a button click operation, the button is the target object. Regardless of the event processing method, the event function will contain an event object. The event object has an attribute target, and the target always points to the target object. The event object also has a property called currentTarget, which points to the DOM element to which the captured or bubbling event flows. From the above description, we know that whether it is a capture event or a bubbling event, the event stream will flow to the document. If we add a click event to the document, the button on the page does not add a click event. At this time, we click the button, and we know The click event on the document will be triggered. One detail here is that when the document click event is triggered, the target of the event is the button instead of the document. Then we can write the code like this:

Copy code The code is as follows:


aa
document.addEventListener("click",function(evt){
        var target = evt.target;
           switch(target.id){
case "btn":
alert("button");
break;
case "aa":
alert("a");
break;
         }
},false);

When we run it, we find that the effect is the same as if we wrote the button event separately. But its benefits are self-evident. One function handles the event functions of the entire page, and no event functions are idle. It is perfect. This solution also has a professional name: event delegation. jQuery's delegate method is based on this principle. In fact, the efficiency of event delegation is not only reflected in the reduction of event functions, it can also reduce DOM traversal operations. For example, in the above example, we add functions on the document. The document is the top-level object in the page, and the efficiency of reading it is very high. , when it comes to specific object events, we do not use DOM operations but use the target attribute of the event object. All of this can only be summarized in one sentence: It is really fast, so fast for no reason.

Event delegation can also bring us a great by-product. Friends who have used jQuery should have used the live method. The feature of the live method is that you can add event operations to page elements, even if this element does not currently exist on the page. , you can also add its events. After understanding the event delegation mechanism, the principle of live is easy to understand. In fact, jQuery's live is done through event delegation, and live is also an efficient way to add events.

After understanding event delegation, we will find that jQuery’s bind method is an inefficient method because it uses the original event definition method, so we must use bind with caution. In fact, jQuery developers have also noticed this problem. The new version There is an on method in jQuery. The on method includes all the functions of bind, live and delegate methods, so I suggest that friends who read this article should abandon the previous method of adding events and use the on function to add events.

Event delegation has another benefit. In the example of event delegation above, I added events to the document. Here I want to make a comparison. In jQuery, we are used to putting the definition of DOM element events in the ready method, as follows Shown:

Copy code The code is as follows:

$(document).ready(function(){
XXX.bind("click",function(){});
});

The ready function is executed after the page DOM document is loaded. It is executed before the onload function. This early benefit has many benefits. One of the benefits is performance improvement. Event definitions such as jQuery are also a standard practice. I believe Some friends must have put certain event bindings outside ready, and finally found that the button will be invalid. This invalid situation sometimes lasts for a moment, and then it gets better. Therefore, we often ignore the principle of this problem and do not bind it to the ready function. Event, this operation is actually to bind the event before the DOM is loaded. During this time period, it is very likely that some elements have not been constructed on the page, so the event binding will be invalid. Therefore, the principle of ready defining events is Ensure that the event of the DOM element is defined after all elements of the page are loaded. However, problems can be avoided when using event delegation. For example, binding the event to the document represents the entire page, so the time when it is loaded is the earliest, so in the document By implementing event delegation, it is difficult for the event to be invalid, and it is also difficult for the browser to report "XXX function is not defined". To summarize this feature: event delegation code can run at any stage of page loading, which will provide developers with greater freedom in improving web page performance or enhancing web page effects.

Now I’ve finished writing this article. Good night.

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template