This is the 8th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

The reason why I mentioned this API today is that when I was using Echarts to implement the chart, there was a scene where data was returned but the chart was not displayed. I wrote that if there was no data, the chart would be displayed as empty, and if there was data, the chart would be displayed. However, I received the data, but the view was blank and empty was not displayed. This.$nextTick is used.

this.$nextTick

This.$nextTick– Defer the callback until after the next DOM update cycle. Use the data immediately after you modify it, and then wait for DOM updates.

This.$nextTick– Just like the global vue.nexttick method, except that the this callback is automatically bound to the instance calling it.

In general, suppose we change the text inside a DOM element, and we want to print the changed text directly after a DOM update.

The official function of this.$nextTick is to perform a delayed callback after the next DOM update loop. Use this method immediately after modifying the data to get the updated DOM.

This brings us to the asynchronous update queue.

Asynchronous update queue

Vue updates the DOM asynchronously. Whenever a data change is heard, vUE opens a queue and buffers all data changes that occur in the same event loop. If the same watcher is triggered more than once, it will only be pushed into the queue once. This removal of duplicate data while buffering is important to avoid unnecessary computation and DOM manipulation. Then, in the next event loop, “TICK,” Vue refreshes the queue and performs the actual (de-duplicated) work.

Using the vm.$nextTick() instance method within a component is particularly convenient because it does not require a global Vue, and this in the callback function is automatically bound to the current Vue instance.

Now that I’ve mentioned above, I’d like to talk about how Vue renders DOM nodes.

Vue renders DOM nodes

Browser Rendering process

The browser receives the HTML file and converts it into a DOM tree
Convert the CSS file to CSSOM

During this process, the browser determines what the style of each node is, and this process can be very resource-intensive. Because styles can be set to a node or inherited. In this process, the browser recurses through the CSSOM tree and determines exactly what style the specific elements are.

Generate render tree

Once we have generated the DOM tree and the CSSOM tree, we need to combine the two trees into a render tree.

In this process, it is not as simple as merging the two. The render tree contains only the nodes that need to be displayed and their style information. If a node is display: None, it will not be displayed in the render tree.

After the browser generates the render tree, it will make the layout (also called backflow) according to the render tree, and then call the GPU to draw, synthesize the layer, and display it on the screen. For this part of the content is too low-level, but also involves hardware related knowledge, here will not continue to expand the content.

Why is DOM manipulation slow

You’ve all heard that manipulating the DOM sucks, but what’s the reason?

Because DOM is something that belongs in the rendering engine, and JS is something that belongs in the JS engine. When we manipulate the DOM through JS, which actually involves communication between two threads, there is bound to be some performance loss. Manipulating the DOM more than once means that threads are communicating with each other all the time, and manipulating the DOM can cause redraw backflow, which can lead to performance issues.

Classic interview question: Insert tens of thousands of DOM, how to achieve the page does not lag?

First of all, we certainly can’t insert tens of thousands of DOM at once, which would definitely cause a lag, so the focus of solving the problem should be how to render the DOM in batches. Most of us can think of a requestAnimationFrame to iterate on the DOM, but there’s another way to solve this problem: virtualized scroller.

The principle of this technique is to render only the content in the visible area, not the non-visible area at all, and replace the rendered content in real time as the user scrolls.

What happens when rendering is blocked

Rendering in the first place requires generating a rendering tree, so HTML and CSS will definitely block rendering. If you want to render faster, the more you should reduce the file size you need to render in the first place, flatten the hierarchy, and optimize the selector.

Then, when the browser parses the script tag, it pauses building the DOM, and when it’s done, it picks up where it left off. That said, if you want the first screen to render as quickly as possible, you should not load JS files on the first screen, which is why it is recommended to place the script tag at the bottom of the body tag.

At the moment, of course, it’s not necessary to put the script tag at the bottom, as you can add defer or async properties to the script tag.

When the script tag adds the defer attribute, it means that the JS file will be downloaded in parallel, but will be executed sequentially after the HTML has been parsed, so you can place the script tag anywhere in this case.

Async property can be added to JS files without any dependencies to indicate that JS file downloading and parsing will not block rendering.

Repaint and Reflow

Redraw and backflow occur frequently when we set the node style, and can greatly affect performance.

  • Redraw is when a node needs to change its appearance without affecting the layout, such as changescolorIt’s called redrawing
  • Backflow is when layout or geometry properties need to be changed.

Backflow must occur redraw, redraw does not necessarily cause backflow. The cost of backflow is much higher, and changing the child node in the parent node is likely to result in a series of backflows in the parent node.

The following actions can cause performance problems:

  • changewindowThe size of the
  • Change the font
  • Add or remove styles
  • Text change
  • Position or float
  • The box model

And what a lot of people don’t know is that redraw and backflow are also related to Eventloop.

  1. Eventloop determines when Microtasks are completeddocumentDoes it need to be updated? Because the browser has a refresh rate of 60Hz and will be updated every 16.6ms.
  2. And then determine if there isresizeorscrollEvent. It would trigger an event if it did, soresizescrollEvents are triggered at least once in 16ms and have throttling functions.
  3. Determines whether a Media Query is triggered
  4. Update the animation and send the event
  5. Check whether a full-screen operation event exists
  6. performrequestAnimationFrameThe callback
  7. performIntersectionObserverCallback, a method used to determine whether an element is visible, can be used on lazy loading, but is not compatible
  8. Update the interface
  9. So that’s what you might do in one frame. If there is free time in a frame, it will be executedrequestIdleCallbackThe callback.

Virtual DOM

Vue tracks how it changes the real DOM by creating a virtual DOM. Take a closer look at this line of code:

return createElement('h1', this.blogTitle)
Copy the code

What exactly does createElement return? It’s not an actual DOM element. It might be more accurately called createNodeDescription, because it contains information that tells the Vue what nodes need to be rendered on the page, including descriptions of their children. We describe such a node as a “virtual node”, often abbreviated to “VNode”. “Virtual DOM” is the name we use for the entire VNode tree built from the Vue component tree.

This.$nextTick application scenario

How does this.$nextTick work?

NextTick: this.$nextTick: this.$nextTick: this.$nextTick: this.$nextTick: this.$nextTick: this.

  • DOM operations performed by the Created () hook function in the Vue lifecycle must be placed in the vue.nexttick () callback. The reason is that the DOM isn’t actually rendering at the time the Created () hook function is executed, and DOM manipulation is useless, so it’s important to put the DOM manipulation js code in the view.nexttick () callback. The equivalent is the Mounted hook function, because when this function is executed, all DOM mounting and rendering have been completed, and any DOM operations in this function should not be a problem.
  • When you set vm.someData = ‘new Value’, the DOM is not updated immediately, but the necessary DOM updates are made when the asynchronous queue is cleared, which is when the next event loop starts. If you try to do something based on the updated DOM state at this point, you’ll have a problem. To wait for Vue to finish updating the DOM after the data changes, use vue.nexttick (callback) immediately after the data changes. This callback will be called after the DOM update is complete.
  • Mounted does not promise that all child components will be mounted together. If you want to wait until the entire view is rendered, replace Mounted with vm.$nextTick