This article should be the last in the vue3 source code reading series. Today we will learn about the virtual DOM of VUe3 and its diff algorithm. The virtual DOM is also an important part of vUE. React and Vue use the virtual DOM, while Angular uses the real DOM. The virtual DOM was also first introduced by React. Today is mainly to learn about vue3 virtual DOM source code and its diff algorithm

VUE3 source code reading notes —- initialization process VUE3 source code reading notes (two) — responsive

What is virtual DOM && and why?

As we all know, dom manipulation in the browser is a bit of a performance drain. The virtual DOM is to use JS to generate and control the DOM, which can improve our page performance and make dom manipulation more convenient. Its essence is a JS object that describes our DOM structure to generate the actual DOM. In addition to performance, there are compatibility issues. When manipulating the DOM, there will inevitably be compatibility issues, but when using the virtual DOM, I can deal with these compatibility issues in JS first and then operate. Of course, the virtual DOM can also be cross-platform, because the DOM is maintained by JS and can be adapted by various platforms. Like applets.

The source code to read

Virtual DOM section

First, where does the source code for the virtual DOM start? Of course, starting with mount, when we mount vue, we will render our templates, using the virtual DOM

// Initialize the vnode
const vnode = createVNode(
  rootComponent as ConcreteComponent,
  rootProps
)
Copy the code

You can see that the first sentence of mount is to create a vnode, which is the virtual DOM. Let’s look at how the vNode is generated. We found the createVNode function.

const vnode: VNode = {
    __v_isVNode: true,
    [ReactiveFlags.SKIP]: true.type,
    props,
    key: props && normalizeKey(props),
    ref: props && normalizeRef(props),
    scopeId: currentScopeId,
    children: null.component: null.suspense: null.ssContent: null.ssFallback: null.dirs: null.transition: null.el: null.anchor: null.target: null.targetAnchor: null.staticCount: 0,
    shapeFlag,
    patchFlag,
    dynamicProps,
    dynamicChildren: null.appContext: null
  }
Copy the code

We can see that the return value of this function is a VNode object. This is the virtual DOM, which contains some information about the DOM structure. Mount is used to generate a VNode object based on our configuration. After that, the vNode will be processed by the patch function. I have seen this before when I looked at the code related to the initialization process. When I saw the patch method, I stopped reading it. I knew that it was a function to handle vNode. Let’s see what patch does. Patch will use renderComponentRoot to initialize the vNode you pass in.

.// Execute the component's render function, where result is vnoderesult = normalizeVNode( render! .call( proxyToUse, proxyToUse! , renderCache, props, setupState, data, ctx ) ) ...return result
Copy the code

This method executes the render function of the root component instance to obtain the corresponding VDOM of the entire app.

const subTree = (instance.subTree = renderComponentRoot(instance))
patch(
  null,
  subTree,
  container,
  anchor,
  instance,
  parentSuspense,
  isSVG
)
Copy the code

Later, we found that after generating VDOM, we traversed through patch, so that children were also generated. The rest of the process is simple, with createElement generating the real DOM.

diff

When the data changes, a new Vnode is generated, so it performs the patch function again to put the old and new vNodes in

patch(
  prevTree, / / the old
  nextTree,	/ / new
  // parent may have changed if it's in a teleporthostParentNode(prevTree.el!) ! .// anchor may have changed if it's in a fragment
  getNextHostNode(prevTree),
  instance,
  parentSuspense,
  isSVG
 )
Copy the code

Again, following the flow, we found the function patchElemnt, and here’s the simplest text change

// text
// This flag is matched when the element has only dynamic text children.
if (patchFlag & PatchFlags.TEXT) {
  if(n1.children ! == n2.children) { hostSetElementText(el, n2.childrenas string)}}Copy the code

When the text changes, a new DOM is generated by calling hostSetElementText. When the whole program is very large, in fact, the internal is the same, when the data changes, first determine what changes, and then through different functions to generate dom.

The Diff algorithm is only for the virtual DOM comparison and higher replacement efficiency. The Diff algorithm is used to obtain the data table of the RESULTS of the Diff algorithm (which operations need to be recorded). The original DOM is still to be operated on the Vue side, but the DOM fragment of JS is used to operate the DOM (unified calculation of all changes after the unified update of the DOM) for a one-time update of the browser DOM. In fact, DOM fragments can be used without having to open them normally, but in this way, programmers can write business code by putting DOM operations into fragments. This is the value of the framework, so that programmers can focus on writing business code.