为什么要使用Virtual DOM
1、前端开发刀耕火种的时代
2、MVVM框架解决视图和状态同步问题
3、模板引擎可以简化视图操作,没办法跟踪状态
4、虚拟DOM跟踪状态变化
5、参考github上virtual-dom的动机描述
(1)虚拟DOM可以维护程序的状态,跟踪上一次的状态
(2)通过比较前后两次状态差异更新真实DOM
虚拟DOM的作用
1、维护视图和状态的关系
2、复杂视图情况下提升渲染性能
3、跨平台
(1)浏览器平台渲染DOM
(2)服务端渲染SSR(Nuxt.js/Next.js)
(3)原生应用(Weex/React Native)
(4)小程序(mpvue/uni-app)
虚拟DOM开源库
1、Snabbdom
(1)Vue.js 2.x内部使用的虚拟DOM就是改造的Snabbdom
(2)大约200SLOC(single line of code)
(3)通过模块可扩展
(4)源码使用TypeScripe开发
(5)最快的Virtual DOM之一
2、virtual-dom
Snabbdom的基本使用
1、步骤
(1)安装 parcel,使用简单
(2)配置 scripts
(3)目录结构
Snabbdom基本使用
1、案例一
import { init } from 'snabbdom/build/package/init'; import { h } from 'snabbdom/build/package/h'; const patch = init([]) //第一个参数:标签+选择器 //第二个参数:如果是字符串就是标签中的文本内容 let vnode = h('div#container.cls','Hello World') let app = document.querySelector('#app') // 第一个参数:旧的VNode,可以是DOM元素 // 第二个参数:新的VNode // 返回新的VNode let oldVnode = patch(app,vnode) vnode = h('div#container.snabbdom','Hello snabbdom') patch(oldVnode,vnode)
执行
npm run dev
案例二
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 h1'), // h('p','hello p') // ]) // patch(oldVnode,vnode); //清除div中的内容 patch(oldVnode,h('!')); }, 2000);
模块的使用
1、官方提供的模板
attributes
props
dataset
class
style
eventlisteners
2、模块的使用步骤
(1)导入需要的模块
(2)init()中注册模块
(3)h()函数的第二个参数处使用模块
3、案例
import { init } from 'snabbdom/build/package/init' import { h } from 'snabbdom/build/package/h' //1、导入模块 import { styleModule } from 'snabbdom/build/package/modules/style'; import { eventListenersModule } from 'snabbdom/build/package/modules/eventlisteners'; //2、注册模块 const patch = init([ styleModule, eventListenersModule ]) //3、使用h()函数的第二个参数传入模块中使用的数据(对象) let vnode = h('div',[ h('h1',{style:{backgroundColor:'red'}},'Hello World'), h('p',{ on: { click: eventHandler } },'Hello p') ]) function eventHandler(){ console.log('干嘛') } let app = document.querySelector('#app'); patch(app,vnode);
Snabbdom源码解析概述
1、Snabbdom的核心
(1)Init()设置模块,创建patch()函数
(2)使用h()函数创建JavaScript对象(VNode)描述真实DOM
(3)patch()比较新旧两个Vnode
(4)把变化的内容更新到真实的DOM树
h函数介绍
作用:创建VNode对象
Vue中的h函数
1、函数重载
(1)参数个数或参数类型不同的函数
(2)JavaScript中没有重载的概念
(3)TypeScript中有重载,不过重载的实现还是通过代码调整参数的
patch整体过程分析
(1)patch(oldVnode newVnode)
(2)把新节点中变化的内容渲染到真实DOM,最后返回新节点作为下一次处理的旧节点
(3)对比新旧VNode是否相同节点(节点的key和sel相同)
(4)如果不是相同节点,删除之前的内容,重新渲染
(5)如果是相同节点,再判断新的VNode是否有text,如果有并且和oldVnode的text不同,直接更新文本内容
(6)如果新的VNode有children,判断子节点是否有变化