Front page lag? Or DOM operations, you need to optimize the code

Source: Internet
Author: User
Tags hosting

The Document Object Model (DOM) is a language-neutral application interface. In the browser, the DOM interface is implemented in the JavaScript language, and the elements in the browser page are manipulated by JavaScript, making the DOM an important part of JavaScript. In the rich client Web application, the UI changes in the interface are implemented through DOM operations and are not implemented by traditional refresh pages. While DOM provides a rich interface for external invocation, DOM operations are expensive, and the performance bottlenecks of the page's front-end code are mostly focused on DOM operations, so one of the main concerns of front-end performance optimization is the optimization of DOM operations. The general principle of Dom operation optimization is to minimize DOM operations.

Before discussing the best performance practices for DOM operations, let's look at why DOM operations affect performance. In the browser, the implementation of the DOM is separated from the implementation of the ECMAScript. For example, in IE, the implementation of Ecmascrit in the Jscript.dll, and the implementation of the DOM in Mshtml.dll, in Chrome using WebCore in WebKit processing dom and rendering, but ECMAScript is implemented in the V8 engine, Other browsers have similar conditions. So invoking the DOM interface through JavaScript code is equivalent to interacting with two separate modules. This cross-module invocation has a high performance loss compared to calls in the same module. But DOM operations have the greatest impact on performance because it causes the browser to redraw (repaint) and rearrange (reflow).

To give you a deeper understanding of the performance impact of redrawing and rearrangement, here's a brief description of the browser's rendering principle (if you want to learn more about how the browser works, see the article, "How the browser works: a new web browser behind the scenes"). From the process of downloading a document to rendering a page, the browser constructs the DOM tree by parsing the HTML document, parsing the CSS to produce the CSS rule tree. The JavaScript code may modify the resulting DOM tree and the CSS rule tree during the parsing process. The render tree is then built from the DOM tree and the CSS rules tree, in which the CSS matches the HTML elements based on the selector. The render tree includes style properties such as the size of each element, margins, and other invisible elements such as hidden elements and head elements in the render tree. Finally, the browser calculates the position of each element based on the coordinates and size of the element, and draws the elements onto the page. Redrawing refers to some parts of the page to be redrawn, such as changes in color or background colors, the position and size of the elements are not changed, the rearrangement is the location or size of the element has changed, the browser needs to recalculate the render tree, causing part or all of the rendering tree to change. After the render tree is re-established, the browser redraws the affected elements on the page. The cost of rearrangement is much higher, and redrawing affects the elements of the part, while reflow can affect all elements. The following DOM operations can result in redrawing or rearrangement:

    • Adding, deleting, and modifying visible DOM elements

    • Page-Initialized rendering

    • Moving DOM elements

    • Modify CSS styles to change the size of DOM elements

    • DOM element content is changed to make the dimension larger

    • browser window size Change

    • browser window scrolling

As you can see, these operations are more common in DOM operations. Modern browsers perform performance optimizations for reflow or redraw, for example, by accumulating a batch of DOM operations and then unifying or redrawing them once. In some cases, however, the browser is immediately re-queued or redrawn. For example, request the following DOM element layout information: offsetTop/Left/Width/Height ,, scrollTop/Left/Width/Height clientTop/Left/Width/Height ,, getComputedStyle() or currentStyle . Because these values are calculated dynamically, the browser needs to finish drawing the page as soon as possible, and then calculate the return value, which disrupts the optimization of reflow or redraw.

Page redraw or rearrangement from DOM operations is unavoidable, but you can follow some best practices to reduce the impact of reflow or redraw. Here are some concrete practical ways to do this:

1. Merging DOM operations multiple times for a single DOM operation

The most common DOM manipulation is the frequent modification of DOM element styles, similar to the following code:

element.style.borderColor = ‘#f00‘;
element.style.borderStyle = ‘solid‘;
element.style.borderWidth = ‘1px‘;

This encoding is caused by frequent changes to the DOM element's style, triggering the page reflow or redraw, described above, the modern browser for this situation has a performance optimization, it will merge DOM operations, but not all browsers have such an optimization. The recommended approach is to combine DOM operations as much as possible, as the above code can be optimized to:

// 优化方案1
element.style.cssText += ‘border: 1px solid #f00;‘;
// 优化方案2
element.className += ‘empty‘;

The code for the sample has two optimizations that combine the styling of multiple styles into a single setting. Scenario 2 has a slight performance loss over scenario 1 because it needs to query the CSS class. But the maintenance of Scenario 2 is the best, as discussed in the previous chapter. Many times, if the performance problem is not prominent, the choice of coding scheme should be given priority to the maintenance of the code.

Similar operations also include modifying the contents of DOM elements through the innerHTML interface. Instead of stitching the HTML code directly through this interface, it is a one-time assignment to the interface of the DOM element when the code is stitched together as a string innerHTML .

2. Change DOM elements offline or hidden

Detach or hide the DOM element from the page stream, which, when processed, causes the page to redraw or reflow only when the DOM element is detached and added, or when it is hidden and displayed, without causing the page's performance problems for DOM element operations that are out of the page layout stream. This approach is suitable for situations where DOM elements need to be modified in large quantities. There are three main ways to do this:

(1) Working with document fragments

A document fragment is a lightweight paper object that is not associated with a particular page. By doing DOM operations on a document fragment, you can reduce the effect of DOM operations on page performance by creating a document fragment and performing the necessary DOM operations on the fragment, attaching it to the page after the operation is complete. The impact on page performance exists only in the last step of attaching a document fragment to a page. The code looks like this:

var fragment = document.createDocumentFragment();
// 一些基于fragment的大量DOM操作
...
document.getElementById(‘myElement‘).appendChild(fragment);

(2) Hide elements by setting the display style of the DOM element to none

This is done by hiding the DOM elements of the page, to remove the elements from the page, and to restore the original display style of the element after a lot of dom manipulation. For this type of operation, which causes the page to redraw or rearrange, there are only two steps to hide and show the DOM element. The code looks like this:

var myElement = document.getElementById(‘myElement‘);
myElement.style.display = ‘none‘;
// 一些基于myElement的大量DOM操作
...
myElement.style.display = ‘block‘;

(3) Cloning DOM elements into memory

This is done by cloning a copy of the DOM element on the page into memory and then manipulating the cloned element in memory, replacing the original DOM element in the page with this cloned element after the operation is complete. In this way, performance-impacting operations are only the last step in replacing elements, and manipulating cloned elements in memory does not result in performance loss on the page. The code looks like this:

var old = document.getElementById(‘myElement‘);
var clone = old.cloneNode(true);
// 一些基于clone的大量DOM操作
...
old.parentNode.replaceChild(clone, old);

In modern browsers, because of the optimization of DOM operations, the performance improvements may not be noticeable after applying the above approach. However, in some old browsers that still occupy the market, using these three coding methods can greatly improve page rendering performance.

3. Set the Position property of the DOM element with the animation effect to fixed or absolute

The animated elements in the page are set to absolute positioning, leaving the elements out of the page layout flow, thus avoiding the frequent reflow of the page, involving only the rearrangement of the animated elements themselves. This practice can improve the performance of the animation effect display. If you set the animation element to absolute positioning and do not meet the design requirements, you can set it to absolute positioning at the beginning of the animation, and then restore the original positioning settings when the animation ends. In many websites, there will be a large display of ads at the top of the page, usually animated and collapsed. If performance optimization is not done, the performance loss of this effect is obvious. Using the optimization scheme mentioned here, you can improve performance.

4. Careful access to DOM element layout information

As discussed earlier, getting the DOM's layout information can have a performance loss, so if there is a duplicate call, it is best to cache the values in local variables as much as possible. Consider one of the following examples:

for (var i=0; i < len; i++) {
    myElements[i].style.top = targetElement.offsetTop + i*5 + ‘px‘;
}

In the code above, the value of an element is repeated in a loop, in offsetTop fact, the value of the element in this code offsetTop does not change, so there is an unnecessary performance loss. The optimized scenario is to get the offsettop value of the element outside the loop, which is simply a call to the value of the element over the previous scenario offsetTop . The changed code is as follows:

var targetTop = targetElement.offsetTop;
for (var i=0; i < len; i++) {
    myElements[i].style.top = targetTop+ i*5 + ‘px‘;
}

In addition, because the layout information of the DOM element forces the browser to refresh the render tree and may cause the page to redraw or reflow, avoid getting layout information for DOM elements when there is a large number of DOM operations, so that the browser's optimizations for high-volume DOM operations are not compromised. If you need these layout information, it's best to get them before DOM operations. Consider one of the following examples:

var newWidth = div1.offsetWidth + 10;
div1.style.width = newWidth + ‘px‘;

var newHeight = myElement.offsetHeight + 10; // 强制页面重排
myElement.style.height = newHeight + ‘px‘; // 又会重排一次

According to the above, the code will trigger the page to recalculate the render tree when it encounters the information of the DOM element, so the code above will cause the page to reflow two times, if the layout information of the DOM element is moved ahead of time, because the browser optimizes the continuous DOM operation, there is actually only one page reflow. The optimized code is as follows:

var newWidth = div1.offsetWidth + 10;
var newHeight = myElement.offsetHeight + 10;

div1.style.width = newWidth + ‘px‘;
myElement.style.height = newHeight + ‘px‘;

5. Binding events Using Event-managed methods

Binding an event on a DOM element affects the performance of the page, on the one hand, the binding event itself consumes processing time, and on the other hand, the browser saves the event bindings, so the bound event also consumes memory. The more events that are bound to the elements in the page, the more processing time and memory are consumed, and the less performance is, so the fewer events that are bound in the page, the better. An elegant approach is to use event hosting, which uses event bubbling to bind event handling only on parent elements, to handle events of all child elements, to determine event source elements according to the parameters passed in the event handler, and to do different processing for different source elements. This makes it unnecessary to bind events to each child element, the number of managed event bindings is less, and the natural performance is improved. This approach also has the flexibility to easily add or remove child elements without having to consider modifying the event bindings as a result of element removal or modification. The sample code is as follows:

// 获取父节点,并添加一个click事件
document.getElementById(‘list‘).addEventListener("click",function(e) { // 检查事件源元素 if(e.target && e.target.nodeName.toUpperCase == "LI") { // 针对子元素的处理 ...
    }
});

In the code above, only the Click event is bound to the parent element, and when the child node is clicked, the Click event Bubbles, and the parent node catches the event and checks the event source element with E.target and handles it accordingly.

In JavaScript, there are browser compatibility issues with event binding, so similar interface methods are available in many frameworks for event hosting. For example, in jquery you can use the following methods to implement event hosting (sample code from the jquery official website):

$( "table" ).on( "click", "td", function() { $( this ).toggleClass( "chosen" );
});

Front page lag? Or DOM operations, you need to optimize the code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.