Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理

什么是 Virtual DOM

  • Virtual DOM(虚拟 DOM),是由普通的 JS 对象来描述 DOM 对象
  • 使用 Virtual DOM 来描述真实 DOM
    Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理_第1张图片

为什么要使用 Virtual DOM

  • 前端开发刀耕火种的时代
  • MVVM 框架解决视图和状态同步问题
  • 模板引擎可以简化视图操作,没办法跟踪状态
  • 虚拟 DOM 跟踪状态变化
    • 虚拟 DOM 可以维护程序的状态,跟踪上一次的状态
    • 通过比较前后两次状态差异更新真实 DOM

虚拟 DOM 的作用和虚拟 DOM 库

虚拟 DOM 的作用

  • 维护视图和状态的关系
  • 复杂视图情况下提升渲染性能
  • 跨平台
    • 浏览器平台渲染DOM
    • 服务端渲染 SSR(Nuxt.js/Next.js)
    • 原生应用(Weex/React Native)
    • 小程序(mpvue/uni-app)等

虚拟 DOM 库

  • Snabbdom
    Vue.js 2.x 内部使用的虚拟 DOM 就是改造的 Snabbdom
    大约 200 SLOC (single line of code) (源码大约就200行,所以研究虚拟DOM使用Snabbdom比研究Vue源码轻松)
    通过模块可扩展(功能强大,类似于插件机制)
    源码使用 TypeScript 开发
    最快的 Virtual DOM 之一
  • virtual-dom

Snabbdom 基本使用

创建项目

安装 parcel
  1. 创建项目目录
md snabbdom-demo
  1. 进入项目目录
cd snabbdom-demo
  1. 创建package.json
npm init -y
  1. 本地安装parcel
npm install parcel-bundler -D

注意:以上操作在 管理员身份运行的cmd窗口中操作,否则可能会在最后一步报错

配置 scripts

安装 parcel 之后,项目目录结构如下
Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理_第2张图片

"scripts": {
    "dev": "parcel index.html --open",
    "build": "parcel build index.html"
  },
目录结构
  1. 根目录下创建入口文件index.html
  2. 创建src目录
    Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理_第3张图片

Snabbdom 文档

  • 看文档的意义
    学习任何一个库都要先看文档
    通过文档了解库的作用
    看文档中提供的示例,自己快速实现一个 demo
    通过文档查看 API 的使用
    (以上题外话_~~~下面提供一个地址感兴趣的阔以看看)
    https://github.com/snabbdom/snabbdom
  • 当前版本 v2.1.0

导入 Snabbdom

创建完项目之后,要导入 Snabbdom

安装 Snabbdom
 npm install snabbdom@2.1.0
导入 Snabbdom
  • Snabbdom 的两个核心函数 init 和 h()
    • init() 是一个高阶函数,返回 patch()
    • h() 返回虚拟节点 VNode
补充
  • 文档中导入的方式
    Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理_第4张图片
  • 实际导入的方式
    parcel/webpack 4 不支持 package.json 中的 exports 字段
    在这里插入图片描述

Demo

通过使用Snabbdom 模拟演示虚拟DOM的实现原理
index.html 引入 01-basicusage.js

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Snabbdom-demotitle>
head>
<body>
    <div id="app">div>
    <script src="./src/01-basicusage.js">script>
body>
html>

01-basicusage.js

  • init函数(返回一个patch函数)作用:把虚拟 DOM 转化为真实 DOM 并挂载到 DOM树上
  • h函数作用:创建虚拟 DOM,这里创建的是 VNode 虚拟节点
  • vnode作用:描述真实 DOM
import { init } from 'snabbdom/build/package/init'
import { h } from 'snabbdom/build/package/h'

const patch = init([])

/**
 * init函数(patch函数)作用:把虚拟 DOM 转化为真实 DOM 并挂载到 DOM树上
 * h函数作用:创建虚拟 DOM,这里创建的是 vnode 虚拟节点
 * vnode作用:描述真实 DOM
 */

/**
 * h函数参数
 * 第一参数:标签+选择器
 * 
 * 第二个参数:
 * 如果是字符串就是标签中的文本内容
 * 如果想要嵌套子元素,则第二个参数是一个数组,数组中每个成员都是一个h函数
 *  
*/
// 创建一个vnode h('标签名#id.class')
let vnode = h('div#container.cls','Hello World')
// 获取页面上的id为app的div
let app = document.querySelector('#app')
// 调用patch 比较两个vnode,把两个vnode的差异更新到真实DOM上
/**
 * patch函数参数
 * 第一个参数:旧的 VNode,也可以是 DOM 元素
 * 第二个参数:新的 VNode
 * 
 * 返回值:返回一个新的 VNode,也就是第二个参数
 * 返回的新 VNode 会作为下一次再调用patch时 旧的 VNode 即 把当前的状态保存起来
 */
let oldVnode = patch(app, vnode)

vnode = h('div#container.xxx','Hello Snabbdom')
patch(oldVnode, vnode)

运行

npm run dev

浏览器执行结果
Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理_第5张图片
index.html 引入 02-basicusage.js

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Snabbdom-demotitle>
head>
<body>
    <div id="app">div>
    <script src="./src/02-basicusage.js">script>
body>
html>

02-basicusage.js

import { init } from 'snabbdom/build/package/init'
import { h } from 'snabbdom/build/package/h'

const patch = init([])

let vnode = h('div#container', [
    h('h1', 'Hello Snabbdom'),
    h('p', '这是一个p')
])

let app = document.querySelector('#app')
let oldVnode = patch(app, vnode)

// 模拟请求服务更新页面数据
setTimeout(() => {
    vnode = h('div#container', [
        h('h1', 'Hello World'),
        h('p', '这是一个ppppppppppp')
    ])
    patch(oldVnode, vnode)

    // 清除div中的内容 '!'表示创建空的注释节点
    // patch(oldVnode, h('!'))
}, 2000)

浏览器执行结果
2s之后页面内容更新
Vue Virtual DOM(虚拟DOM)、使用Snabbdom模拟虚拟DOM实现原理_第6张图片


相关资源:Snabbdom 基本使用、了解Vue 虚拟DOM实现使用的Snabbdom

你可能感兴趣的:(Vue,vue.js,dom操作,dom)