Post

2019-10-29 React Visual Dom

VirtualDOM


面试中都被问到react中的virtual dom

1.什么是虚拟dom?

当然,首先去查看react官方文档

概念: react中虚拟dom主要是指react dom,当你编写一个组件之后,react不是直接去操作dom的,而是会生成一些虚拟dom,保存在内存中,然后再去跟真实的dom同步,一一匹配。react的fiber是来管理虚拟dom的,存放组件树的附加信息。

动机:

  1. 直接操作dom,速度会很慢。
  2. 这种方式赋予了React声明式的API:你告诉React希望让UI是什么状态,React就确保DOM匹配该状态。这使得用户可 以从属性操作,事件处理,和手动DOM更新这些再构建应用程序时必要的操作中解放出来

说道react的virtual dom,则必须了解react的 Diffing算法

下面详细讲一讲什么是Visual Dom

前言 react总的diff并不是第一次出现,之前的算法复杂度是O(n^3),O是节点的个数,也就是说如果你有1000个节点,那么它的复杂度就是一亿次。 这样是会影响react性能的,所以react做了改进,它的复杂度是O(n)

它的算法基于了以下三点

  1. 不同类型的component,生成的树是不一样的,或者说大部分时候是不一样的,我记得官方文档说,还没有出现过不同类型的component,生成树是一样的这样issue

PS:平常自己写代码的时候,也有这点体会

  1. 同一层级的一组节点加元素key,这个key必须是唯一的,稳定的值,react根据key值来进行树的更新,删除,移动等操作
  2. 忽略UI中的节点跨层级移动

对于diff算法,react分成了下面三种不同的类型

  1. 1.tree

    将old tree 和 new tree进行比较,如果new tree中的某个节点不存在,react会直接删除掉这个节点,不会再做其他的对比,这样只需要对dom节点进行一次遍历

    那么如果对DOM 中跨层级的节点是怎么进行操作的呢

    两个tree进行比较,如果节点不存在,直接删除,再进行重建

PS:很麻烦是不是,所以不建议频繁的对DOM节点进行移动和删除,保持稳定的DOM结构有助于性能的提升

  1. 2.component

    2.1同一类型的节点比较遵从 tree diff比较v-dom树

    2.1不同类型的,先将组件归类为dirty component,替换下整个组件的节点

    2.3同一类型virtual dom没有变化, react允许用shouldComponentUpdate() 来判断该组件是否进行diff,运用得当可以节省diff时间,提升性能

PS:应当避免类型不同,结构相同的组件

  1. 3.node节点

    对于同一层级的节点,react有以下三种操作

    3.1插入

    3.2移动

    3.3删除

    react非常建议在同一层级的一组节点中加上KEY,能够非常大的提升性能

    那么react是怎么管理key值呢

    react先回对新集合进行遍历,for(name in nextChildren),通过key值判断两个集合中是否有相同的节点,if(prevChild === nextChild),如果为TRUE,则进行移动,移动之前会进行位置比较,如果true,则进行操作

    当然这种也有短板,比方说将一组节点中的第一个节点和最后一个节点互换位置,理论上来说,进行一次节点互换就行,但是react会操作最后一个节点之前的所有节点到相应的位置,这样会影响性能的渲染。

    所以react非常不建议将一个树的节点从最后一位移到第一位

  1. 在一个list最后插入元素,react将会进行挨个对比,才会插入元素,
  2. 在一个list开始插入元素,react也会进行挨个对比,才会插入元素,这些都是无效的
This post is licensed under CC BY 4.0 by the author.