React的Fiber和diff,与Vue2对比
1、Fiber:
在V15的时候,react采用的是同步更新的策略,但是当组件树庞大的时候,同步更新一鼓作气的更新就会造成组件的一些函数无法执行,浏览器主线程一直被react占用,比如键盘输入等指令就无法执行,此时的用户体验会非常差。所以V16中Fiber出现了。
破解JavaScript中同步操作时间过长的方法其实很简单——分片。React Fiber把更新过程碎片化,执行过程如下面的图所示,每执行完一段更新过程,就把控制权交还给React负责任务协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有紧急任务,那就去做紧急任务。有点类似CPU线程调度了
维护每一个分片的数据结构,就是Fiber。
为了防止一个更新过程可能被打断,所以React Fiber一个更新过程被分为两个阶段(Phase):第一个阶段Reconciliation Phase和第二阶段Commit Phase。在第一阶段Reconciliation Phase,React Fiber会找出需要更新哪些DOM,这个阶段是可以被打断的;但是到了第二阶段Commit Phase,那就一鼓作气把DOM更新完,绝不会被打断。
2、为什么没有Vue fiber?
主要就是其数据劫持时刻监听,导致的更新精细度问题,vue可以做到父子嵌套,父组件更新时,子组件不更新;而react会自顶向下全更新。其响应式的原理不同。
参考:https://developer.51cto.com/article/704554.html
因为react无法做到vue那么精细,所以他在创建虚拟dom树做对比的时候,所创建的会比vue大,所以更新的时候开销也更大,其更需要fiber。fiber结构就类似树,但是他有三个索引,可以指向第一个子节点、父节点和兄弟节点,是一个大链表。所以当他被打断时会有断点,可以继续执行
vue精细程度高,开销更大,要权衡更新的程度;且因为vue为模板语法静态编译,所以没有jsx灵活
3、react和vue的diff。
参考:https://blog.csdn.net/weixin_44403976/article/details/123607037
https://juejin.cn/post/7116141318853623839
相同点:和Vue一样,都是同级比较。都需要key做map才能diff性能最大化
不同点:vue的diff算法是父子兄弟组件互不干扰的;vue的diff算法的比较规则是新旧列表的两端对比;vue的diff算法的移动规则:不同情况的移动规则不同
react的diff算法更新父组件,其子组件全更新,可以用shouldComponentUpdate处理;react比较规则是从左到右依次比较;react移动规则:依次移动。深度优先
Vue3的diff,对比还是双端对比,移动使用最长递增子序列:使用最少的移动完成节点的更新,选择最长的子序列,移动剩下的。二分+贪心。nlogn
由于 Vue 是通过 template 模版进行编译的(模板生成render函数),所以在编译的时候可以很好对静态节点(静态节点就是一个元素节点,而且这个节点里面没有任何动态的内容,就是说没有绑定任何动态的属性,没有加{{}},没有会变化的子组件等,这叫静态节点)进行分析然后进行打补丁标记,然后在 Diff 的时候,Vue2 是判断如果是静态节点则跳过过循环对比,而 Vue3 则是把整个静态节点进行提升处理,Diff 的时候是不过进入循环的,所以 Vue3 比 Vue2 的 Diff 性能更高效。而 React 因为是通过 JSX 进行编译的,是无法进行静态节点分析的,所以 React 在对静态节点处理这一块是要逊色的。
Vue2 和 Vue3 的比对和更新是同步进行的,这个跟 React15 是相同的,就是在比对的过程中,如果发现了那些节点需要移动或者更新或删除,是立即执行的,也就是 React 中常讲的不可中断的更新,如果比对量过大的话,就会造成卡顿,所以 React16 起就更改为了比对和更新是异步进行的,所以 React16 以后的 Diff 是可以中断,Diff 和任务调度都是在内存中进行的,所以即便中断了,用户也不会知道。