虚拟DOM和diff算法
1. DOM操作非常耗费性能
以前用jquery,可以自行控制DOM操作的时机,手动调整
Vue和React是数据驱动视图,如何有效控制DOM操作?
2. 有了一定复杂度,想减少计算次数比较难
能不能把计算,更多的转移为js计算?因为js执行速度很快。DOM变化的对比放在js层来做,真实操作DOM是‘昂贵’的
vdom-->用js模拟DOM结构,计算出最小的变更,操作DOM
<div class="aaa" id="div1"> <p>vdom</p> <ul style="font-size:20px"> <li>a</li> </ul> </div>
用js模拟DOM结构,上面的html转成下面的结构
{ tag:'div', props:{ className:'aaa', id:'div' }, children:[{ tag:'p', children:'vdom' },{ tag:'ul', props:{style:'font-size:20px'}, children:[{ }] }] }
3.通过snabbdom学习vdom
生成vnode:h函数:传入tag元素、属性、子节点等,返回vnode数据结构return { sel, data, children, text, elm, key };
patch函数-->patch(vnode, newVnode),对比tag,对比tag与key,对比children
updateChidren==>更新children==>key的重要性
const snabbdom = window.snabbdom // 定义 patch const patch = snabbdom.init([ snabbdom_class, snabbdom_props, snabbdom_style, snabbdom_eventlisteners ]) // 定义 h 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) })
4. diff算法-->最大程度减少渲染的范围,通过把DOM通过js去模拟,找出最小变更和范围
dif算法是vdom中最核心和最关键的部分
diff算法能在日常使用vue React中体现出来(如key)
5.diff算法概述
diff即对比,是一个广泛的概念,如 linux diff,git diff
两个js做对比
两棵树做diff,这里的vdom diff
6.树diff的时间复杂度 O(n^3)
1.遍历第一棵树
2.遍及第二棵树
3.排序
三次循环,1000个节点,要计算1亿次,算法不可用
===>
优化时间复杂度到O(n)
1.0 只比较同一层级,不跨级比较
2.0 tag不同,则直接删掉重建,不深度比较
3.0 tag和key,两者都相同,则认为是相同节点,不再深度比较
7.diff算法源码-->生成vnode:h函数:传入tag元素、属性、子节点等,返回vnode数据结构return { sel, data, children, text, elm, key };
patch函数-->patch(vnode, newVnode),对比tag,对比tag与key,对比children
updateChidren==>更新children==>key的重要性
8.vdom和diff算法总结
细节不重要,核心概念很重要:h,vnode,patch,diff,key