区别于真实DOM
问题
:数据发生改变,试图怎么更新
当数据改变时,会触发setter,并且通过Dep.notify去通知所有订阅者Watcher(组件),订阅者们就会调用patch方法,给真实DOM打补丁,更新相应的视图。
计算最小更新 DOM 的方式。
流程图:
其中包含 patch
函数、pachVnode
函数、UpdateVnode
函数(未详细介绍)
使用 snabbdom 虚拟 DOM 库 :snabbdom
/** src/index.js */
import { init } from 'snabbdom/init'
import { classModule } from 'snabbdom/modules/class'
import { propsModule } from 'snabbdom/modules/props'
import { styleModule } from 'snabbdom/modules/style'
import { eventListenersModule } from 'snabbdom/modules/eventlisteners'
import { h } from 'snabbdom/h' // helper function for creating vnodes
// 1、创建出 patch 函数
const patch = init([
classModule,
propsModule,
styleModule,
eventListenersModule
])
// 2、使用 h 函数创建虚拟节点
const vnode1 = h('ul', {}, [
h('li', {}, 'A'),
h('li', {}, 'B'),
h('li', {}, 'C'),
h('li', {}, 'D')
])
// 3.创建空的容器
const container = document.getElementById('container')
// 4.将 DOM 塞入container
patch(container, vnode1)
const vnode2 = h('ul', {}, [
h('li', {}, 'A'),
h('li', {}, 'B'),
h('li', {}, 'C'),
h('li', {}, 'D'),
h('li', {}, 'E')
])
// 点击按钮时,将vnode1变为vnode2
const btn = document.getElementById('btn')
btn.onclick = function () {
// 使用最小改变 来达到 新的vnode 覆盖 旧的 vnode2
patch(vnode1, vnode2)
}
接收参数存在: element(真实 DOM ) 和 vnode(虚拟 DOM ) 两种类型
首次插入
有两个使用场景:判断 key 和 sel 是相同
场景 | 1、vnode.key 和 vnode.sel 都相同 | 2、vnode.key 或 vnode.sel 不同 |
---|---|---|
是否同一个Vnode | 是 | 否 |
结果 | 更新(调用 pachVnode ) | 创建新的DOM,删除老的DOM |
虚拟节点 text 和 children 最多只能有一个
3个情况 | 1、新 vnode === 旧 vnode(全等) | 2、新 Vnode :无 text | 3、新 Vnode :有 text |
---|---|---|---|
不需更新,返回 | 1.新、老 Vnode 都有 children,即调用(updateChildren );2.老 Vnode 无 children,即添加 children ; 3.新的无 children ,即删除 children | 删除 children ,更新新的 text |