This is the second day of my participation in the November Gwen Challenge. Check out the details: the last Gwen Challenge 2021

Virtual DOM

  • Virtual DOM(Virtual DOM) is a common JS object to describe the DOM object
  • Real DOM members, first printing out all DOM members
let element = document.querySelector('#app')
let s = ''
for(let key in element){
	s += key + ','
}
console.log(s)
Copy the code
  • A DOM has many members, and the cost of creating a real DOM is very high
  • Virtual DOM
{
  sel:'div',
  data:{},
  children:undefined,
  text:'hello world',
  elm:undefined,
  key:undefined
}
Copy the code
  • The creation cost is much lower than the real DOM

Why use the Virtual DOM

  • You need to manipulate both the DOM and the data
  • The MVVM framework addresses view and state synchronization issues
  • The template engine simplifies view operations. There is no way to track state, so you have to delete all page elements and then create all page elements.
  • The virtual DOM tracks state changes
  • Virtual-dom motivation description on Github
    • The virtual DOM can maintain the state of the program, keeping track of the last state
    • Update the real DOM by comparing the two states

The role of the virtual DOM

  • Maintain the relationship between views and states

  • Improved rendering performance in complex view situations

  • cross-platform

    • Browser platforms render the DOM
    • Server render SSR(nuxt.js/Next-js)
    • Weex/React Native
    • Small programs (MPvue /uni-app), etc
  • Virtual DOM open source library

    • Snabbdom
      • The virtual DOM used internally in vue.js2. X is a modified Snabbdom
      • Approximately 200 SLOC (single line of code)
      • Extensible through modules
      • Source code uses TypeScript
      • One of the fastest Virtual DOM
    • Virtual-dom
      • One of the first open source libraries for the virtual DOM

Basic use of Snabbdom

  • Create a project

    • Steps:
      • Install the parcel
CD snabbdom-demo // Create package.json NPM init -y // Install parcel NPM install locally parcel-bundler -DCopy the code
  • The configuration scripts
"scripts":{
	"dev":"parcel index.html --open",
  "build":"parcel index.html"
}
Copy the code
  • The directory structure
index.html
package.json
src
	01-basicusage.js
Copy the code
  • index.html
<! DOCTYPE html> <html lang='cn'> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Inital -sacle=1.0"> <meta http-equiv=" x-UA-compatiable "content="ie=edge"> <title>Vue</title> </head> <body> <div id="app"></div> <script src="./src/01-basicuage.js"></script> </body> </html>Copy the code
  • Snabbdom document
    • Snabbdom document
// 01-basicusage.js import {init} from 'snabbdom/init' import {h} from 'snabbdom/h' Exports in package.json // exports in package.json 'snabbdom/build/package/init', 'snabbdom/build/package/h const patch = init ([]) / / h function of the first parameter: label + selector, the second parameter: Let vnode = h('div#container. CLS ','Hello world') let app = document.querySelector('#app') // the first argument, Old VNode, which can be a DOM element // second argument: Let oldVNode = patch(app, VNode) VNode = h('div#container. XXX ','Hello Snabbdom') // compare the old and new VNode, Update patch(oldValue, vnode)Copy the code
  • demo
// 02-basicusage.js import { init } from 'snabbdom/build/package/init' import { h } from 'snabbdom/build/package/h' Const patch = init([]) // The second argument is an array because the child elements are also vNodes, Let vnode = h('div#container',[h('h1','Hello') h('p','p tag ')]) let app = document.querySelector('#app') let  oldVNode = patch(app, SetTimeout (() => {vnode = h('div#container',[h('h1','Hello World') h('p','Hello P tag ')]) Patch (oldValue, vnode) // Clear the contents of div, '! 'Empty comment node patch(oldVnode, h('! '))}, 2000)Copy the code

Snabbdom module

  • Functions of modules
    • Snabbdom’s core library does not handle DOM element attributes/styles/events, only VNodes, by registering modules that Snabbdom provides by default
    • Modules in Snabbdom can be used to extend the functionality of Snabbdom
    • Modules in Snabbdom are implemented by registering global hook functions
  • Officially provided modules
    • Attributes: Sets vNode attributes. The internal DOM standard method is implemented using setAttribute, which handles Boolean attributes internally
    • Props: Properties are set as object points without judging the properties of the Boolean type
    • Dataset: Used to dataset data-custom properties in HTML5
    • Class: it is not used to set the class style. It is used to switch the class style. Setting the class style can be done by an argument to the h function
    • Style: Sets inline styles
    • Eventlistensers: Registration event
  • How to use a module
    1. Import the required modules
    2. Register modules in init
    3. The second argument to h uses a function
// 03-modules.js import { init } from 'snabbdom/build/package/init' import { h } from 'snabbdom/build/package/h' // 1. The import module import {styleModule} from 'snabbdom/build/package/modules/style' import from {eventListenersModule} 'snabbdom/build/package/modules/eventlisteners' // 2. Const patch = init([styleModule, eventListenersModule]) // 3 Let vnode = h('div', [h('h1', {style:{backgroundColor: 'red' } },'Hello World'), h('p', { on: { click: eventHandler }}, Function eventHandler() {console.log('eventHandler')} let app = document.querySelector('#app') let oldVNode = patch(app, vnode)Copy the code

Snabbdom source code parsing

  • The core of Snabbdom

    • Init () sets up the module and creates the patch function

    • Use the h() function to create JavaScript objects (vNodes) that describe the real DOM

    • Patch () compares the old and new vNodes

    • Update the changed content to the real DOM tree

  • Snabbdom source

    • Source code address: github.com/snabbdom/sn… (Version: V2.1.0)

    • Git clone -b v2.1.0 –depth=1 github.com/snabbdom/sn…

  • Source directory

-.vscode: editor configuration files - examples: official examples - perf: performance tests - SRC: source code - the rest are configuration files, don't careCopy the code
  • examples:

    • There are four examples, two of which end in SVG,

    • Hero: Demonstrates custom modules

    • Reord-animation: demonstrates a list of transitions

  • Take a look at an example

    • The build directory does not exist in the current directory. You need to install dependencies and compile them

    • npm i

    • npm run compile

    • At the end of compilation, the directory produces a build directory

    • Open an external browser to run through Open with Live Server

  • SRC directory

    • Source package:

      • helpers

        • Attachto. ts: Data structure that defines AttachData

      • modules

        • Six official modules, and one custom module in the Hero example

        • Modules. ts: Defines all the hook functions used

      • H ts: defines h functions to create vNodes

      • Hooks. Ts: Defines all the hook functions in the lifecycle

      • Htmldomapi.ts: Wrap dom elements, create elements, delete elements, etc

      • Init. ts: Defines init function, loads module and API, and returns patch function

      • Jsx-golbal. ts: type declaration file for JSX

      • Jsx. ts: handles JSX

      • Thunk. Ts: Optimizations for handling complex views

      • Tovnode. ts: provides a function to convert a node to a vnode. The patch function can be the first node, which needs to be converted

      • Vnode. ts: Defines the vNode data structure

      • What is left is the configuration file in SRC

  • Test: unit test

H function

  • Creates a VNode object
  • H function in Vue
new Vue({
	router,
  store,
  render: h => h(App)
}).$mount('#app')
Copy the code
  • The h function, first seen in HyperScript, uses JavaScript to create hypertext

  • Function overloading

    • A function with a different number of arguments or type of arguments, dependent on the argument, independent of the return value

    • There is no concept of overloading in Javascript

    • There are overloads in Typescript, but the implementation tweaks parameters through code

VNode

The patch process

  • patch(oldVnode, newVnode)

  • Render the changing contents of the new node into the real DOM, and return the new node as the old node for the next processing.

  • Check whether the old and new VNodes are the same (the key and SEL of the nodes are the same).

  • If it is not the same node, delete the previous content and re-render

  • If it is the same node, check whether the new VNode has text. If it has text and is the same as the text of oldVnode, update the text content directly

  • If the new VNode has children, check whether the children have changed