Hello, I’m Carson.

It is said that Chinese people pay attention to the golden mean, but are Chinese man-made frames particular?

This article explains in principle how Vue maintains a moderate balance between runtime and compile time.

UI = fn(state)

The working principle of almost all front-end frames can be summarized by the following formula:

UI = fn(state)

The UI (view) can be computed from State (state) through FN (frame).

However, in principle, there are many differences between the frameworks.

They can be divided into three categories based on update granularity:

  • Update the tree level
  • Component-level update
  • Node-level update

There is no superior update granularity, just for different implementations

Let’s take a brief look at how the different granularity updates are implemented.

Suppose you have the following component tree, where Cpn is a custom component with an internal structure of ul>li*2:

We want to update a li in Cpn to yellow:

Update the tree level

The framework updated at the tree level regenerates a complete virtual DOM tree, which is compared with the corresponding nodes of the previous virtual DOM tree during the generation process:

When the changed node is found, the corresponding DOM operation is performed.

The tree-level update framework is characterized by:

  • Dependency on Virtual DOM
  • Don’t care about the node that triggered the update (because it will be found through the full tree comparison of the virtual DOM)

The most famous framework for this update approach is React.

Component-level update

The above example, if the component level update framework.

It will find the component where the trigger update node is located and generate the virtual DOM tree of this component (instead of the virtual DOM tree of the whole tree). During the generation process, it will compare with the corresponding node of the virtual DOM tree before this component:

When the changed node is found, the corresponding DOM operation is performed.

The component-level update framework is characterized by:

  • Dependency on Virtual DOM
  • Care about the node that triggered the update (the virtual DOM comparison is applied to the component where the node is located)

The best known framework for this update approach is Vue.

Node-level update

If it is a node-level update framework, the corresponding method will be generated directly according to the DOM change corresponding to the state change during compilation, and the corresponding method will be called directly after the state change.

In the example above, the color state is associated with the changeColor method at compile time:

function changeColor(newColor) {
  li.style.color = newColor;
}

When the color state is changed, the changeColor method is called directly to update the LI corresponding DOM.

The characteristics of the node-level update framework are:

  • Do not rely onVirtual DOM, rely on precompilation (establish state and changeDOMBetween methods).
  • Care about the node that triggered the update (the node state corresponds to the update method one to one)

The best known framework for this update approach is SVelte.

The doctrine of the mean of Vue3

VUE is the representative of component-level updates, and the granularity of updates is between tree level and node level. Is it center-left or center-right?

Vue3 said.

I’m going to do a repeated crosswise. I’m going to do both

VUE3 contains three types of tree structures:

Describes the view tree -> virtual DOM tree -> real DOM tree

The tree that describes the view is officially recommended to use template syntax, but JSX can also be used.

Either way, you end up with a virtual DOM tree.

When using JSX, Vue3 has the flexibility of the React runtime, and Vue3 can be viewed as an enhanced version of React + Mobx

When using template syntax, VUE3 introduces precompilation. At this point, the VUE3 workflow can be broken down into four steps:

View tree -> VNode tree -> Block array -> real DOM tree

The VNode tree is the virtual DOM tree in the conventional sense, and the Block array is the array composed of those vnodes in the VNode tree that are dependent on the state and will change.

For example, for the following template syntax:

<template>
  <section>
    <div>i am</div>
    <p>{{name}}</p>
  </section>
</template>

Section and div contain no state and do not change, so they are converted to vnodes, but have no corresponding Block.

P contains the state name, which translates to VNode and Block.

When the name state of the component in which this template is located changes, the vnodes of section, div, and p need to be created and compared in turn.

With precompilation, you only need to traverse the Block array for comparison.

Using the example above, we only need to compare one Li node:

In this case, it’s a component-level update framework that uses the virtual DOM, but it’s pretty close to a node-level update framework.

conclusion

This article introduces three different types of frameworks in terms of update granularity, and VUE3’s flexibility between flexibility and update granularity in choosing JSX and template syntax.

Can be said to be in line with the golden mean.

Some people might ask, since most Vue3 users are comfortable with template syntax, why not just ditch the virtual DOM and use precompilation to do true node-level updates?

On the one hand, virtual DOM takes the framework out of the concrete view layer and facilitates cross-end rendering.

On the other hand, the VUE2 community ecosystem has accumulated a large number of virtual DOM-based libraries.

What would you do in this situation?