Note source: Hook Education – big front end employment Training camp

Content: Notes, thoughts and experiences in the process of learning

Virtual DOM

Course objectives

  • What is the virtual DOM and what does it do
  • Basic use of the SNabbDOM library
  • Snabbdom source code parsing

Virtual DOM – Virtual DOM

Virtual DOM: DOM pairs are described by ordinary JS objects to reduce the performance overhead of DOM operations

// Use the virtual Dom to describe the real Dom, representing some core properties inside the real object

{
  sel: 'div'.data: {},
  children: undefined.text: 'hello Vitual Dom'.elm: undefined.key: undefined
}
Copy the code

Why use the Virtual DOM

  • Dom is complex to write and performance consuming to operate
  • The MVVM framework addresses view and state synchronization issues
  • The template engine simplifies view manipulation, but does not track state
  • The virtual DOM can track state changes

See Vittual-dom on gitHub

  • The virtual DOM maintains the state of the program, keeping track of the last state
  • Update the real DOM by comparing the two states

Function of virtual DOM

  • Maintain the relationship between views and states
  • Improve rendering performance in complex views
  • Cross-platform: browser, server, native application, applets, etc

Virtual DOM library

Snabbdom library

  • The virtual DOM used by Vue2. Xx is modified based on SNabbDOM
  • The core function has about 200 lines
  • Extensibility through modules: Functions that are not used by core functions can be added through the module mechanism
  • Source code is developed using TypeScript
  • One of the fastest Virtual DOM

Virtual – dom library

Basic use of snabbDOM

Install the Parcel packaging tool

Using WebPack is also possible, but Parcel provides a configured environment for easy packaging

  • Initialize the project to generate package.json:npm i init -y
  • Install a Parcel as a development dependency:npm i parcel-bundler -D

The configuration scripts

Create an entry file index. HTML in the root directory and import the required JS file

Package. json configures the scripts field and adds two commands"scripts": {
    // With parcel, index.html is the entry file and automatically opens the browser
    "dev": "parcel index.html --open".// Package the entry file as index.html
    "build": "parcel build index.html"
}
Copy the code

** Install and use snabbDOM ** also refer to the Chinese documentation

To learn about any library, read the documentation first, learn about the function of the library through the documentation, see the examples provided in the documentation, create a quick demo yourself, see the API usage through the documentation

Install snabbdom: NPM I snabbdom

// Document demo parsing, my own understanding, but the rendering mechanism is not clear

// Introduce functionality
import {
  // Init and h are both core snabbDOM features
  init,
  h,
  // The following four are third-party features
  classModule,
  propsModule,
  styleModule,
  eventListenersModule,
} from "snabbdom"

// Initialize snabbDOM and inject functionality into it (note: initialization must be written, even if no third-party functionality needs to be injected)
const patch = init([classModule, propsModule, styleModule, eventListenersModule])

// Get the node
const container = document.getElementById("container");

// Use the h function to create a node - div element - id container - class names two and classes
const vnode = h("div#container.two.classes", {
  // Event object to which to add the event to be implemented
  on: {
    // Click the event
    click: someFn
  }
}, [ 
  // This contains the child node
  h("span", {
    / / style
    style: {
      // Write style
      fontWeight: "bold"}},"Old text"),// Finally, you can write the content text
  // You can also write content text directly
  "Old".// Create a new node
  h("a", {
    // Attribute Settings
    props: {
      // Set the pointing address
      href: "/foo"}},"Old text"),])// Perform the first render comparison
patch(container, vnode);


// Create a new node
const newVnode = h(
  "div#container.two.classes", {
    on: {
      click: anotherEventHandler
    }
  },
  [
    h(
      "span", {
        style: {
          fontWeight: "normal".fontStyle: "italic"}},"New text"
    ),
    " 新的",
    h("a", {
      props: {
        href: "/bar"}},"New text"),])// Then compare the render
patch(vnode, newVnode)


// Two event functions
function someFn() {
  console.log(111)}function anotherEventHandler() {
  console.log(222)}Copy the code

The basic use

// Introducing features: Init and H are both core snabbDOM features
import { init, h } from "snabbdom"

// Create a virtual node
let vnode = h('div#app.content'.'I'm virtual node content')
// Get the existing node
const app = document.getElementById('app')
// Initialize snabbDOM, must write, even if [] is empty
const patch = init([])
Oldnode is used to receive the status for the next comparison
let oldnode = patch(app, vnode)
// Reset the virtual node
vnode = h('p.text'.'I am the new virtual node content')
// Compare render again, again store the state this time
oldnode = patch(oldnode, vnode)
Copy the code

Note: You may need to change the import path if there are problems with init and H import, but I did not find any problems with the latest version

Contain child nodes

// Introducing features: Init and H are both core snabbDOM features
import { init, h, vnode } from "snabbdom"

// Get the existing node
const app = document.getElementById('app')

// Initialize snabbDOM, must write, even if [] is empty
const patch = init([])

// Create a virtual node
let vNode = h('div#box'[// Set 2 to an array in which to write child nodes
  // Create a virtual node using the h function
  h('h1'.'title'),
  h('p'.'content'),
  'Text can be passed in directly without using h function'
])

// Render the virtual node
let oldNode = patch(app, vNode)


// Special notation, set to comment gpa can be cleared
patch(vNode, h('! '))
Copy the code

Module USES

The module function

  • Snabbdom core functionality cannot handle DOM attributes, styles, events, and so on
  • Use the default module provided in snabbDOM to achieve this, and the module can extend the snabbDOM function
  • Modules are implemented using globally registered lifecycle hook functions

The following modules are officially available

  • Attribures: Handles inherent attributes
  • Props: Same as above, but can’t handle Boolean-type properties
  • Dataset: used to process a custom property starting with data-
  • Class: To switch classes, but the core function is already available, so it is generally not used
  • Style: Performs style processing
  • The process of events is ongoing

Using the step

  • Import the required modules
  • Register modules in init
  • The second argument to the h function uses a module
// Introducing features: Init and H are both core snabbDOM features
// When importing modules, be careful not to write the import name incorrectly
import { init, h, classModule ,propsModule ,styleModule ,eventListenersModule } from "snabbdom"

// Get the existing node
const app = document.getElementById('app')

// Inject modules at initialization time
const patch = init([classModule ,propsModule ,styleModule ,eventListenersModule])

// Create a virtual node
let vNode = h('div#box', {
  // The position of argument 2 uses the object for module use
  // Use the style module
  style: {
    backgroundColor: 'red'.// Note that this is an inline style that needs to be written in units
    width: '200px'.height: '200px'
  },
  // Use the event module
  on: {
    // Add the click method
    click: c
  }
}, [
  / / child nodes
  h('h1'.'title'),
  h('p'.'content'),
  'Text can be passed in directly without using h function'
])

// Render the virtual node
let oldNode = patch(app, vNode)


// The event function
function c() {
  console.log(1111)}Copy the code

Snabbdom source code parsing

To study the source code

  • The macro understanding
  • Look at the source code with the target
  • Look at the source code process to understand
  • debugging
  • The resources

The core function

  • Init () sets up the module and creates the patch () function
  • Use the h () function to create JS objects (vNodes) that describe real DOM nodes
  • Patch () compares the old and new vNodes
  • Update the changed content to the real DOM tree

The source code of cloning

Use the official Githyb source address – course version V2.1.0 – I used V3.0.1

  • Cloning code: git clone – b v2.1.0 – the depth = 1 https://github.com/snabbdom/snabbdom.git

  • Clone + V2.1.0 + last commit + address

  • Structural analysis:

    • .vscode directory: Editor configuration (no concern)
    • Examples directory: officially provided example demo
    • Perf directory: Performance tests (no concern)
    • SRC directory: source files
    • The rest of the configuration files don’t need attention
  • Install dependency: NPM I

  • Package: NPM run compile – here the package command is compile, unlike vue, the vuild directory is the dependencies we use when installing dependencies in other projects

  • Run examples/reorder-animation/index.html to see the effect. Use liveserver instead of opening the file. We may find that clicking the Sort and delete buttons will not work because the code in this example is not updated with the version update. We need to modify it manually

  • Try modifying the examples/reorder-animation/index.js code to find all click events and change click: [remove, movie] to click () {remove(movie)}

H () function

Used to create vNode-virtual DOM objects

Vue uses the h function to render the Vue instance, using the H function in the render option. In short, Vue relies on the H function inside the render option to perform virtual DOM operations

new Vue({
  router,
  store,
  // Use the h function for DOM manipulation
  render: h= > h(App)
}).$mount('#app')
Copy the code

Function overloading: a function of the same name with a different number or type of arguments that executes different code depending on the arguments passed in

Js does not have the concept of overloading, but type Script does, but the implementation of overloading requires code to adjust parameters

H function uses ts function overloading, internally by judging the number of arguments passed, different types and finally return a vNode function call, the real virtual node creation is realized by VNode

Vnode function

The inside of the function simply specifies some properties inside the virtual DOM node

Patch overall process analysis

Syntax: patch (old node, new node)

  • Render the bina content of the new node to the real node, and finally return the new node as the old node for the next comparison
  • Compare whether the old and new nodes are the same, judge whether the unique identifier (key) and node type (SEL) of each node are the same
    • If not the same node (sel different) delete previous content and re-render
    • If it’s the same node
      • Compare whether the new node has text. If it has text with the old node, it will be directly compared with the new text content
      • If the new node has child nodes, determine the change of child nodes

The init () function

Init is used to create a patch, and the patch function is the return value of init

The init function encapsulates some lifecycle functions that can be used by a closure formed by patch as a return value, and init takes an array to receive other functions

The patch function

Compare the old and new nodes

creatElm

When the old and new nodes are different

Create a DOM element based on the new virtual node passed in and the internal child node and return it

patchvnode

Be responsible for finding and rendering differences between old and new nodes when they are the same

Update Children overall analysis

The old and new virtual nodes have child nodes for comparison

The Diff algorithm

Diff algorithm for the virtual DOM: Find the difference between nodes of two trees

Snabbdom optimizes the traditional DIff algorithm according to the characteristics of DOM

  • Dom manipulation rarely involves cross-level manipulation of nodes
  • Only nodes of the same level are compared

I was stunned. Come on. The world is not worth it