在群里看到有人提到React fiber,写一点个人的看法。
Fiber这个东西很有意思,我觉得它不是一蹴而就的,引出它的可能是性能问题,然后在这个思路上走下去发现了更多有意思的东西。

组件树是一个可能会很大很深的树,一次性的渲染通常需要递归地遍历整个树,这样在树很深的时候可能会导致栈溢出错误,而且整个渲染过程可能很长,导致掉帧。

解决的办法很简单,如果递归过程中可以随时退出并保存上下文,就像多线程切换时会保留栈那样,那么就可以分多次的遍历完整个树。

实现方式就是把在遍历过程中原本在栈上的数据保存成数据结构,比如当前遍历节点,它的children列表,上一级节点等,这个数据结构就是fiber。于是原本的遍历渲染变成了,遍历建立fiber树,然后分多次的遍历fiber树进行渲染。不过fiber实际上组成的不是一个树而是图,react把子节点实现成了链表,通过fiber的sibling连接起来,这样会有更好的遍历性能。

于是就会发现,原本的线性的栈现在变成了一个结构化的图,后者除了不会有栈溢出和可以部分遍历之外,还有一些有意思的区别。首先,栈是对计算机友好的线性结构,但是不容易调试,它随遍历过程递进又随之回退,我们几乎只能借助调试器来观察现场。而fiber是一个持久的结构,任何时候我们可以直接观察它整个的状态。其次,它使react的代码更加简明了,它将遍历和逻辑解偶了,不管是渲染还是什么只要对待一个fiber节点处理就好了。

这些区别产生的结果就是解放了想象力,一旦走到这里这个框架就形成了,react可以在fiber上加入更多功能而不必局限于最初对栈的模拟的初衷。比如用alternate(也是个fiber节点)保存最新的渲染结果,这样就可以异步地渐进式地更新整个UI,于是有了Time Slicing和Suspence。更进一步的,在fiber上保存和读取副作用,于是就有了hooks,函数组件一跃成为更好用的存在,函数线性的语法结构不仅让代码变短了,也更容易重构了。

这些想象力的产物又增加了生产力,比如有了React.lazy实现loading效果变得非常简单,那么设计师就可以设计更加用户友好的UI。Web之所以在用户界面上超越了native应用就是因为这方面生产效率高,所以越来越多的electron应用出现。我认为React的不断创新可能也会悄悄的改变UI的形态,而fiber的出现是一个重要的拐点。
展开
评论