说明:
虚拟dom是真实dom的JS对象,它里面包含标签名、属性、子标签和文本节点。组件渲染时会调用render函数,它会创建虚拟dom树,再生成真实dom后再挂载到页面,优点是减少频繁操作真实dom和减少重绘,提高性能。
原理:
实现原理主要包括以下3部分:1.用JS对象模拟真实dom并进行抽象;2.用diff算法来比较新旧虚拟dom树的差异从而最小化更新视图;3.用patch算法来将这些差异应用到真实dom中。整个流程是数据改变触发setter方法,进一步触发Dep.notify()方法来通知订阅者Watcher,然后执行patch方法,它接受两个参数就是新旧vnode,然后通过key判断是否为同类标签,若是就执行patchVnode方法进行深度对比,它内部判断新旧vnode是否相等,相等就return,不相等就分4种情况比对并且以新vnode的结果为准。(1)旧vnode和新vnode都有文本节点就用新文本替换旧文本;(2)旧vnode没有子节点而新vnode有那就添加新vnode的子节点;(3)旧vnode有子节点而新vnode没有那就删除旧vnode的子节点;(4)新旧vnode都有子节点那就需要用diff算法来比对它们的子节点,使用updateChildren方法做同级比对,同级比对采用首尾指针法,就是头头、头尾、尾头、尾尾的方式来依次比较,当比较成功后就退出当前比较,然后start和end向中间靠拢一格,直到start跑到end右侧才终止比较。如果都匹配不到就用新旧虚拟dom的key(唯一标识)来比较,如果key相同就复用,并移动到新虚拟dom的位置。
diff算法的作用:
用来修改DOM的一小段,不会引起dom树的重绘
key的作用和原理:
key是虚拟dom对象的唯一标识,作用是高效更新虚拟dom。当数据变化会生成新的虚拟dom,然后进行新旧虚拟dom的比较。对比规则是:
1.当旧虚拟dom找到新虚拟dom的key,若内容没变则直接使用之前的真实DOM,若内容变了则生成新的真实DOM,并替换掉之前的真实DOM。
2.当旧虚拟dom未找到新虚拟dom的key,则创建新的真实DOM,随后渲染到到页面。
v-for中的key:
<li v-for="(item,index) in xxx" :key="item.id"></li>
v-for指令的key值优先使用唯一字符串(性能最高), 实在没有就用下标index
1.没有key值(默认是下标) : 不复用,就地更新
2.key值为下标(相当于没设置) : 不复用,就地更新
3.key值是id : 复用相同的key,更新不同的key
虚拟DOM是由多个VNode形成的树结构,即虚拟dom树。VNode是虚拟节点,全称是Virtual Node。