With the popularity of Vue, React, and Angular, it’s possible that we don’t need to manipulate the DOM as much these days, and the three frameworks have a huge advantage in side-interactive manipulation. Because we know that scripting DOM manipulation is expensive, this article focuses on what you might not know about regular DOM manipulation.

DOM in the browser

First, let’s take a look at what DOM is and why it’s slow.

DOM is by nature slow

The Document Object Model (DOM) is a W3C (World Wide Web Consortium) standard that is a language-independent programming interface for manipulating XML and HTML documents. While the DOM is a language-neutral API, its interface in the browser is implemented in JS. However, browsers usually implement DOM and JS separately. For example, DOM in Chrome is implemented as webCore in WebKit, while JS engine is Google’s own V8. Since separated, once the two need to create a connection, there is a price to pay.

DOM access and modification

As mentioned earlier, there is a performance cost associated with JS accessing the DOM, and modifying DOM elements is even more expensive because it causes the browser to recalcitate the geometry of the page. Look at both ends of the code:

Regular loop operations

Dom loop operations

The first code defines a normal variable that loops over and executes events that are almost zero. In the second piece of code, the loop accesses a particular element twice each time: first reading the innerHTML property of the element, and then overriding it the second time. As you can see, it takes approximately 2.8 seconds to execute, and the script blocks subsequent execution. With this in mind, it’s not hard to come up with a more efficient version:

Execute last before dom manipulation

Use a local variable wrapper for each update, wait for the loop to end, and write to the page once (as much work as possible to the JS part). You can see it’s nearly 2,000 times faster. It’s obvious. The more times you access the DOM, the slower your code will run, so the general rule of thumb is to reduce the number of DOM accesses and leave the operations to JS as much as possible. This is one of the reasons why Vue or React design the Virtual DOM in the first place: map the dom model into a JS object, manipulate the JS object instead of directly manipulating the DOM, and then perform innerHtml or append.

HTML collection

Let’s start with a piece of code:

At first glance, this code simply doubles the number of divs on the page: iterating through all of them, creating new ones at a time and adding them to the body. But in reality, this is an infinite loop: the loop exit condition, Alldivs.length, increases after each loop, because the collection of HTML elements reflects the real-time state of the underlying document elements. There are problems with HTML collections like the following:

  1. document.getElementsByTagName()

  2. document.getElementsByClassName()

  3. Document. The getElementsByName ()… .

The second performance problem with the above code is that it needs to access the LENGTH property of the DOM object every time. We can also use a variable to cache the object’s length property:

Redraw and rearrange

The browser displays all the “components” of a page, including HTML tags, JS, CSS, images — and then parses and generates two internal data structures:

DOM tree (representing page structure) Render tree (representing how DOM nodes should be represented) Each node in the DOM tree that needs to be displayed has at least one corresponding node in the render tree. The nodes in the render tree are called frames or boxes, and the CSS box model defines a page element as a box with padding, margin, borders, and position. Once the render tree is built, the browser starts displaying page elements, a process called paint.

When a DOM change affects an element’s geometry (width, height) – such as changing the border width or adding text to a paragraph that increases the number of lines – the browser needs to recalculate the element’s geometry, as well as the geometry and position of other elements on the page. The browser will remove the affected parts of the render tree and rebuild it, a process called “reflow.” After the rearrangement is complete, the browser redraws the affected parts into the browser, a process called repaint.

If you change something other than the element’s geometry, such as changing the element’s background color, there is no rearrangement, only one redraw, because the element’s layout has not changed. Both redrawing and rearranging are expensive operations that cause the UI of your Web application to become unresponsive, and should be minimized as much as possible. When does the rearrangement take place?

  • Add or remove visible DOM elements

  • Element position changes

  • Element size changes (padding, margin, border, height, width)

  • Content changes (text changes or image sizes change)

  • The page renderer is initialized

  • Browser window size changed

  • The appearance of a scrollbar (which triggers a rearrangement of the entire page)

Change the style

Consider this example:

In the example, three styles of the element are changed, and each affects the element’s geometry. In the worst case, this code triggers three rearrangements (most modern browsers are optimized for this and only trigger one). On the other hand, this code accesses the DOM four times and can be optimized.

Batch modify DOM

When you need to perform a series of operations on a DOM element, follow these steps:

  1. Takes the element out of the document flow

  2. Apply multiple changes to it

  3. Bring the element back into the document

In the above combo, moves 1 and 3 trigger a rearrangement, respectively. But if you ignore these two steps, any changes made in step 2 will trigger a rearrangement.

Here are three ways to get DOM elements out of the document flow:

  1. Hidden elements

  2. Use document fragments to build a subtree outside the current DOM and copy it back into the document

  3. Copy the original element to a node out of the document, modify the copy, and replace the original element when done

Take the animation element out of the document flow

In general, rearrangement affects only a small part of the render tree, but it can affect a large part, or even the entire render tree. The fewer rearrangements required by the browser, the faster the application will respond. Imagine a situation where there is an animation at the bottom of the page that slides over the rest of the page. This would be an expensive and massive rearrangement! Users are also bound to feel a sense of page-to-page congestion. Therefore, most of the reordering of pages can be avoided using the following steps:

  1. Use absolute positioning to keep animated elements on the page out of the document flow

  2. Animation display stage

  3. At the end of the animation, the element is restored to its position.

IE的:hover

Starting with IE7, IE allows the :hover CSS selector to be used on any element. However, if you have a large number of elements using :hover, you will find that the thief is slow!

about

Author: monkeyWang

My home page: https://monkeywangs.github.io/

Wechat public account: will push the front end technology articles irregularly, welcome to pay attention to