Vue2系列-Virtual DOM

136 阅读4分钟

面试了许多求职者,很多求职者只知其然,而不知所以然,写此文章为广大前端小伙伴指引迷津。纯干货!纯干货!纯干货!

目录

Virtual DOM

什么是Virtual DOM?

答:将真实的DOM的数据抽取出来,以对象的形式模拟树形结构。

Virtual DOM的作用?

答:避免昂贵的DOM操作与大量无谓的计算量,通过diff算法,一边比较新旧节点一边给真实的DOM打补丁。

diff的原理?
1.找到对应的真实dom,称为`el`
2.父级进行比较更新
3.如果两者都有子节点,则执行`updateChildren`函数比较子节点,

updateChildren如下:

  • Vnode的子节点VcholdVnode的子节点oldCh提取出来
  • oldChvCh各有两个头尾的变量StartIdxEndIdx,它们的2个变量相互比较,一共有4种比较方式。如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦StartIdx>EndIdx表明oldChvCh至少有一个已经遍历完了,就会结束比较。

现在分别对oldS、oldE、S、E两两做sameVnode比较,有四种比较方式,当其中两个能匹配上那么真实dom中的相应节点会移到Vnode相应的位置,这句话有点绕,打个比方

  • 如果是oldS和E匹配上了,那么真实dom中的第一个节点会移到最后
  • 如果是oldE和S匹配上了,那么真实dom中的最后一个节点会移到最前,匹配上的两个指针向中间移动
  • 如果四种匹配没有一对是成功的,分为两种情况
  • 如果新旧子节点都存在key,那么会根据oldChild的key生成一张hash表,用S的key与hash表做匹配,匹配成功就判断S和匹配节点是否为sameNode,如果是,就在真实dom中将成功的节点移到最前面,否则,将S生成对应的节点插入到dom中对应的oldS位置,S指针向中间移动,被匹配old中的节点置为null。
  • 如果没有key,则直接将S生成新的节点插入真实DOM(ps:这下可以解释为什么v-for的时候需要设置key了,如果没有key那么就只会做四种匹配,就算指针中间有可复用的节点都不能被复用了)
diff的比较方式?

答:前端操作dom的时候了,不会把当前元素作为上一级元素或下一级元素,很少会跨越层级地移动DOM元素,在采取diff算法比较新旧节点的时候,比较只会在同层级进行, 不会跨层级比较,因此复杂度的问题转换成 O(n) 复杂度的问题。

diff的弊端?

答:相同⽗元素的⼦元素必须有独特的 key,否则重复的 key 会造成渲染错误。

Vue vs React
  • 相同点
    • 都是两组虚拟dom的对比(react16.8之后是fiber与虚拟dom的对比)
    • 只对同级节点进行对比,简化了算法复杂度
    • 都用key做为唯一标识,进行查找,只有key和标签类型相同时才会复用老节点
    • 遍历前都会根据老的节点构建一个map,方便根据key快速查找
  • 不同点
    • react会自顶向下全diff.
    • vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。
    • react在diff遍历的时候,只对需要修改的节点进行了记录,形成effect list,最后才会根据effect list 进行真实dom的修改,修改时先删除,然后更新与移动,最后插入
    • vue 在遍历的时候就用真实dominsertBefore方法,修改了真实dom,最后做的删除操作
    • react 采用单指针从左向右进行遍历
    • vue采用双指针,从两头向中间进行遍历
    • react的虚拟diff比较简单,vue中做了一些优化处理,相对复杂,但效率更高

小白也是新手面试官,欢迎领导莅临指导工作,提出建议,小白不胜感激,不喜勿喷,点赞收藏随机送程序媛小姐姐一枚哦!!!