react-fiber学习


React Fiber 学习心得

React为什么要使用fiber?

React 15 使用深度递归来更新dom,

由于递归执行一旦开始就无法中断,

当层级很深时,

用户交互就会卡顿。

甚至失去响应。

Fiber的作用

同步更新变为可中断异步更新。

将工作分解为多个工作单元,

给每个工作单元一定的时间(

  在每一帧的时间中,留出一些时间给js线程, 
  
  React利用这些时间更新组件,
  
  源码中可以看到预留的初始时间是5ms),

如果时间不够或者执行完一个工作单元没有剩余时间 (
  
  当预留的时间不够用时,React将线程控制权交还浏览器使其有时间渲染ui,
  
  React则等待下一帧的到来继续被中断的工作。
),

让出执行权给浏览器,

让浏览器重渲。

等浏览器空闲下来,

再重新执行之前暂停的任务。

这样不会影响浏览器绘制,

就不会出现失帧卡顿的现象。

什么是Fiber

从运行机制上来讲:
   
   是一种流程让出机制。
   
从数据角度来讲:
  
   是一种数据结构,或者一个执行单元。
   

Fiber节点与Diff算法

首次执行 ReactDom.render 会创建 fiberRootNode (源码中叫fiberRoot)、 和 rootFiber。
  
fiberRootNode 和 rootFiber 不同点在于,

ReactDom.render 渲染不同的组件树,他们会有不同的 rootFiber。

但整个应用的根节点只有一个,

那就是 fiberRootNode。

————————————————————————————————————————————————————————————-

fiberRootNode 的 current 会指向已渲染内容fiber树,

被称为 current fiber树。

Fiber双缓存

在内存中构建并直接替换的技术叫做双缓存。

React使用双缓存来完成Fiber树的构建与替换一一对应着dom树的创建与更新。

————————————————————————————————————————————————————————————-
  
React 中对多会存在两棵 Fiber 树,

当前屏幕上显示的对应的Fiber树成为 current Fiber 树, 正在内存中构建的称为 workInProgress Fiber 树,

current Fiber树中的Fiber节点被称为current fiber,

workInProgress Fiber树中的Fiber节点被称为workInProgress fiber,

他们通过alternate属性连接。
currentFiber.alternate === workInProgressFiber;

workInProgressFiber.alternate === currentFiber;
React应用的根节点通过current指针在不同Fiber树的rootFiber间切换来实现Fiber树的切换。

当workInProgress Fiber树构建完成交给Renderer渲染在页面上后,

应用根节点的current指针指向workInProgress Fiber树,

此时workInProgress Fiber树就变为current Fiber树。

每次状态更新都会产生新的workInProgress Fiber树,

通过current与workInProgress的替换,完成DOM更新

Diff算法

jsx 生成的虚拟dom对象与当前current fiber 节点 对比产生的workInProgress fiber节点的过程叫Diff算法。

这个对比过程发生在在render阶段。

————————————————————————————————————————————————————————————-
  
同层对比,key 或者 type 任意一个不同直接删除,不用再Diff。

通过key来提供复用的线索。

Fiber节点之间的关系

// 指向父级Fiber节点
return

// 指向子Fiber节点
child

// 指向右边第一个兄弟Fiber节点
sibling

虚拟dom

一个包含了标签类型、属性props 以及他包含子元素的children对象。

虚拟dom的优势

1.封装了可变的属性,不变的属性不放入虚拟dom生成的对象。

例如一个li就有307个属性,无论vue、react 都只对未来可能会变的属性进

行动态封装,使用了{}包裹,这样不用全部对比,是不是更好?

2.兼容性和跨平台的考虑

react 还支持reactNative做原生app

3. 渲染优化 

多次 setState 页面也只会渲染一次

5.让研发专注于业务和数据处理,而不是陷入繁杂的dom增删改查中。

注意: 虚拟dom性能比原生操作dom慢,三大框架皆是如此。

6.单点刷新而不是整个替换

React合成事件

jsx生成的对象的props里会带onClick,

在 beginwork 阶段解析上述数据为fiber结构 memoizedProps 和pendingProps。

什么是React合成事件

React模拟原生事件所有能力的一个对象,拥有和原生事件相同的接口。

根节点 root 上监听所有支持的事件,

当事件触发并冒泡至根节点时,

React将事件内容封装交给 SyntheticEvent。

所以当事件触发的时候,使用统一的分发函数dispatchEvent将指定函数执行。 (执行派发函数)

为什么React要使用合成事件?

React想做一个全浏览器的框架,

这样就得提供全浏览器一致的事件系统,

以此来抹平不同浏览器间的差异。

合成事件的优点

1.使用事件委托的方式避免dom上绑定过多的事件处理函数,

优化了页面性能和内存占用。

2.将单个或多个原生事件合成并包装为合成事件,

合成事件在底层抹平了不同浏览器的差异,

在上层面向开发者暴露统一的、稳定的、与 DOM 原生事件相同的事件接口。

开发者们由此便不必再关注烦琐的底层兼容问题,

可以专注于业务逻辑的开发。

React合成事件和原生事件执行顺序

原生事件会先执行,

而后是React合成事件,

最后是根节点的事件。
注意: 

  不建议将原生事件和React合成事件混用,
  
  因为如果在原生事件中使用了阻止冒泡,
  
  那么就会影响React合成事件的冒泡,
  
  导致根节点上的监听无法触发。
 
值得注意的是:

  合成事件中使用阻止冒泡,
  
  不会影响原生事件。

文章作者: KarlFranz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 reprint policy. If reproduced, please indicate source KarlFranz !
评论
  目录