2019-10-29 React Visual Dom
- VirtualDOM
- 1.什么是虚拟dom?
- 当然,首先去查看react官方文档
- 概念: react中虚拟dom主要是指react dom,当你编写一个组件之后,react不是直接去操作dom的,而是会生成一些虚拟dom,保存在内存中,然后再去跟真实的dom同步,一一匹配。react的fiber是来管理虚拟dom的,存放组件树的附加信息。
- 动机:
- 说道react的virtual dom,则必须了解react的 Diffing算法
- 下面详细讲一讲什么是Visual Dom
- 它的算法基于了以下三点
- 对于diff算法,react分成了下面三种不同的类型
- 将old tree 和 new tree进行比较,如果new tree中的某个节点不存在,react会直接删除掉这个节点,不会再做其他的对比,这样只需要对dom节点进行一次遍历
- 那么如果对DOM 中跨层级的节点是怎么进行操作的呢
- 两个tree进行比较,如果节点不存在,直接删除,再进行重建
- 2.1同一类型的节点比较遵从 tree diff比较v-dom树
- 2.1不同类型的,先将组件归类为dirty component,替换下整个组件的节点
- 2.3同一类型virtual dom没有变化, react允许用shouldComponentUpdate() 来判断该组件是否进行diff,运用得当可以节省diff时间,提升性能
- 对于同一层级的节点,react有以下三种操作
- 3.1插入
- 3.2移动
- 3.3删除
- react非常建议在同一层级的一组节点中加上KEY,能够非常大的提升性能
- 那么react是怎么管理key值呢
- react先回对新集合进行遍历,for(name in nextChildren),通过key值判断两个集合中是否有相同的节点,if(prevChild === nextChild),如果为TRUE,则进行移动,移动之前会进行位置比较,如果true,则进行操作
- 当然这种也有短板,比方说将一组节点中的第一个节点和最后一个节点互换位置,理论上来说,进行一次节点互换就行,但是react会操作最后一个节点之前的所有节点到相应的位置,这样会影响性能的渲染。
- 所以react非常不建议将一个树的节点从最后一位移到第一位
VirtualDOM
面试中都被问到react中的virtual dom
1.什么是虚拟dom?
当然,首先去查看react官方文档
概念: react中虚拟dom主要是指react dom,当你编写一个组件之后,react不是直接去操作dom的,而是会生成一些虚拟dom,保存在内存中,然后再去跟真实的dom同步,一一匹配。react的fiber是来管理虚拟dom的,存放组件树的附加信息。
动机:
- 直接操作dom,速度会很慢。
- 这种方式赋予了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)
它的算法基于了以下三点
- 不同类型的component,生成的树是不一样的,或者说大部分时候是不一样的,我记得官方文档说,还没有出现过不同类型的component,生成树是一样的这样issue
PS:平常自己写代码的时候,也有这点体会
- 同一层级的一组节点加元素key,这个key必须是唯一的,稳定的值,react根据key值来进行树的更新,删除,移动等操作
- 忽略UI中的节点跨层级移动
对于diff算法,react分成了下面三种不同的类型
- 1.tree
将old tree 和 new tree进行比较,如果new tree中的某个节点不存在,react会直接删除掉这个节点,不会再做其他的对比,这样只需要对dom节点进行一次遍历
那么如果对DOM 中跨层级的节点是怎么进行操作的呢
两个tree进行比较,如果节点不存在,直接删除,再进行重建
PS:很麻烦是不是,所以不建议频繁的对DOM节点进行移动和删除,保持稳定的DOM结构有助于性能的提升
- 2.component
2.1同一类型的节点比较遵从 tree diff比较v-dom树
2.1不同类型的,先将组件归类为dirty component,替换下整个组件的节点
2.3同一类型virtual dom没有变化, react允许用shouldComponentUpdate() 来判断该组件是否进行diff,运用得当可以节省diff时间,提升性能
PS:应当避免类型不同,结构相同的组件
- 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非常不建议将一个树的节点从最后一位移到第一位
- 在一个list最后插入元素,react将会进行挨个对比,才会插入元素,
- 在一个list开始插入元素,react也会进行挨个对比,才会插入元素,这些都是无效的
This post is licensed under CC BY 4.0 by the author.