- 一、Vdom
- 二、Diff算法—Vdom的核心
- 三、snabbdom使用
- 四、Vdom和diff算法总结
- 五、vue中patch过程
一、Vdom
1.原生dom操作特点
(1)复杂的dom操作费时消耗性能
(2)以前用jquery,可以自行控制操作时机
2.数据驱动下dom操作方案 - Vdom
(1)虚拟dom核心思想
将更多的计算转移到js上,用js模拟dom,计算出最小更新,再进行原生dom操作
(2)用js模拟dom结构
一般会用tag描述标签名;props描述属性;children描述子元素
(3)snabbdom — 强大简洁的vdom工具库
vue是参考snabbdom实现的vdom和diff,vue3重写了vdom但是基本理念不变
二、Diff算法—Vdom的核心
diff算法能在日常使用中体现(如给元素添加key),也是前端面试热门宠儿
1、diff概念
diff是一个常见的概念,git 有diff命令,js中两个对象可以做diff(jiff工具),两颗树形结构也可以做diff,比如vodm 的diff
2.优化后的diff策略,时间复杂度降低到了O(n)
(1)只比较同一层级,不跨级比较
(2)tag不相同,则直接删掉重建,不再深度比较
当tag不相同时,猜测不一样,即使子元素相同。满足百分之80的情况
(3)当tag和key相同时,认为节点一样,不再深度比较
三、snabbdom使用
const h = snabbdom.h
const container = document.getElementById('container')
// 生成 vnode
const vnode = h('ul#list', {}, [
h('li.item', {}, 'Item 1'),
h('li.item', {}, 'Item 2')
])
patch(container, vnode)
document.getElementById('btn-change').addEventListener('click', () => {
// 生成 newVnode
const newVnode = h('ul#list', {}, [
h('li.item', {}, 'Item 1'),
h('li.item', {}, 'Item B'),
h('li.item', {}, 'Item 3')
])
patch(vnode, newVnode)
// vnode = newVnode // patch 之后,应该用新的覆盖现有的 vnode ,否则每次 change 都是新旧对比
})
1.h函数
接受参数,生成vnode
第一个参数sel: 标签名+选择器
第二个参数data:标签信息,可包含标签属性和事件绑定等
第三个参数children:子元素
2.patch方法
对比新旧vnode差异,再更新到真实dom
第一个参数:真实dom节点或者就vnode对象
第二个参数:新vnode或者null
3.patch过程
(1)调用sameVnode对比新旧VNode是否相同节点(节点的key和sel相同)
(2)如果不是相同节点,删除之前的内容,重新渲染
(3)如果是相同节点,再判断新的VNode是否有text,如果有并且和oldVnode的text不同直接更新文本内容(patchVnode)
(4)patcheVnode对比新旧VNode差异,如果新的VNode有children,调用updateChildren判断子节点是否有变化
(5)如果不满足上面其中特殊情况,遍历新节点children在旧节点children中查找是否有相同key的节点
a.如果存在相同key值节点,判断sel是否相同,如果相同,则调用patchVnode方法进行对比更新并修改对应index
b.如果不存在相同节点,则判断为新增节点,并渲染
四、Vdom和diff算法总结
五、vue中patch过程
1.patch方法
数据更新后,setter会触发patch方法,对比新旧vnode,然后进行视图更新
(1)通过isSameVnode方法判断是否为同一节点
a.vnode的tag和key值同时相等时,认定为相同节点
b.如果不是同一节点,删除旧节点,然后插入新节点