Virtual dom and Snabbdom source code analysis

Virtual DOM

What is virtual DOM

        Virtual DOM (virtual DOM) is a common JS object to describe the real DOM object. Because it is not a real DOM object, it is called Virtual DOM. Real DOM members need to create a lot of attributes, etc. Using virtual DOM to describe DOM will be very concise and reduce performance overhead.

The structure of the virtual DOM

 {
    
     sel:'div', data:{
    
    }, children:undefined, text:'Hello Virtual DOM' elm:undefined, key:undefined } 

Node type of virtual DOM

Element node: node type 1;
attribute node: node type 2;
text node: node type 3;
comment node: node type 8;
document node: node type 9;

Why use virtual DOM

  1. Manual DOM operation is more troublesome, and browser compatibility issues need to be considered. Although there are libraries such as JQuery that can simplify DOM operations, as the project becomes more complex, the complexity of DOM operations increases.

  2. In order to simplify the complex operations of the DOM, various MVVM frameworks have emerged, which solve the problem of synchronization of views and states.

  3. In order to simplify the operation of the view, we can use the template engine, but because it did not solve the problem of tracking dynamic changes, Virtual DOM appeared.

  4. The advantage of virtual DOM is that it does not need to update the DOM immediately when the state changes. You only need to create a virtual tree to describe the DOM. VIrtual DOM will figure out how to effectively update the DOM.

  5. The virtual DOM can maintain the state of the program and track the last state.

  6. Update the real DOM by comparing the two state differences before and after.

What is the role of virtual DOM

  1. Maintain the relationship between views and states
  2. Improve rendering performance in complex view situations. In addition to rendering DOM, SSR (Nuxt.js/Next.js), native applications (Weex/React Native), small programs (mpvue/uni-app), etc. can also be implemented.

Snabbdom of Virtual DOM library

  • The Virtual DOM used inside Vue 2.x is the modified Snabbdom

  • About 200 SLOC (single line of code)

  • Scalable through modules

  • Source code is developed using TypeScript

  • One of the fastest Virtual DOM

Note: Snabbdom's core library cannot handle element attributes, styles, events, etc. If you need to handle it, you can use modules to support it.

Common modules of Snabbdom library:

  • attribute

    • To set the attributes of the Dom element, use setAttribute()
    • Handling Boolean attributes
  • props

    • Similar to the attribute module, set the Dom attribute element[attr] = value
    • Don't handle boolean attributes
  • class

    • Switch class style
    • Note: Setting the class attribute to the element is through the sel selector
  • dataset

    • Set custom attributes of data-*
  • eventlisteners

    • Register and remove events
  • style

    • Set inline style, support animation
    • delayed/remove/destory

Snabbdom source code analysis

How to learn the source code

  • First understand
  • Look at the source code with a goal
  • The process of looking at the source code does not ask for thorough understanding
  • debugging
  • Reference

Snabbdom core content

  1. Use the h() function to create a JavaScript object (VNode) to describe the real DOM

  2. init() sets the module and creates patch() where init() is a higher-order function (returns a function inside a function)

  3. patch() compares the new and old two VNodes

  4. Update the changed content to the real DOM

Snabbdom source code analysis

h function

h() function introduction

  • I have seen the h function when using vue

    new Vue({
          
          
        router,
        store,
        render: h => h(App)
    }).$mount('#app')
    
  • The h() function was first seen in hyperscript, using JavaScript to create hypertext

  • The h() function in Snabbdom is not used to create hypertext, but to create VNOde

Function overloading

  • concept

    • Functions with different numbers or types of parameters
    • There is no concept of overloading in JavaScript
    • There are overloads in TypeScript, but the implementation of overloads is to adjust parameters through code
  • Reload

    function add (a,b) {
          
          
        console.log(a,b)
    }
    function add (a,b,c) {
          
          
        console.log(a + b + c)
    }
    add(1, 2)
    add(1, 2, 3)
    

Modules

In order to ensure the streamlining of the core library, Snabbdom delegates the processing of element attributes/events/styles to the module. Modules can be introduced on demand, and the core of the implementation is based on Hooks. Modules in Snabbdom are hook functions of modules that can be extended by themselves

  • Start when the pre patch function starts to execute
  • Triggered before the init createElm function starts executing Triggers before converting VNode into a real DOM
  • The create ceeateElm function is called after the end of the call to create the real DOM.
  • At the end of the insert patch function, the real DOM is added to the DOM tree and triggered
  • The prepatch patchVnode function is called at the beginning, and it is triggered before the difference between two Vnodes is started.
  • The update patchVnode function calls two Vnodes at the beginning of the comparison process, which is slightly later than prepatch
  • The two Vnodes are called at the end of postpatch patchVnode and executed after the comparison is over.
  • destroy removeVnodes => invokeDestoryHook is called before the element is deleted, and the destroy of the child node is also triggered
  • Triggered when the calling element in remove removeVnodes is deleted
  • The last call of the post patch function

Source code location: src/h.ts

export function h(sel: string): VNode;
export function h(sel: string, data: VNodeData): VNode;
export function h(sel: string, children: VNodeChildren): VNode;
export function h(sel: string, data: VNodeData, children: VNodeChildren): VNode;
export function h(sel: any, b?: any, c?: any): VNode {
    
    
  var data: VNodeData = {
    
    }, children: any, text: any, i: number;
  if (c !== undefined) {
    
    
    data = b;
    if (is.array(c)) {
    
     children = c; }
    else if (is.primitive(c)) {
    
     text = c; }
    else if (c && c.sel) {
    
     children = [c]; }
  } else if (b !== undefined) {
    
    
    if (is.array(b)) {
    
     children = b; }
    else if (is.primitive(b)) {
    
     text = b; }
    else if (b && b.sel) {
    
     children = [b]; }
    else {
    
     data = b; }
  }
  if (children !== undefined) {
    
    
    for (i = 0; i < children.length; ++i) {
    
    
      if (is.primitive(children[i])) children[i] = vnode(undefined, undefined, undefined, children[i], undefined);
    }
  }
  if (
    sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g' &&
    (sel.length === 3 || sel[3] === '.' || sel[3] === '#')
  ) {
    
    
    addNS(data, children, sel);
  }
  return vnode(sel, data, children, text, undefined);
};

Guess you like

Origin blog.csdn.net/weixin_40599109/article/details/108096080