加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 系统 > 正文

React 架构的演变历史

发布时间:2021-05-12 18:51:56 所属栏目:系统 来源:互联网
导读:Fiber 数据结构 我们先回顾一下 Fiber 节点的数据结构(之前文章省略了一部分属性,所以和之前文章略有不同): function FiberNode(tag, key ){ //节点 key ,主要用于了优化列表diff this. key = key //节点类型;FunctionComponent:0,ClassComponent:1,Host

Fiber 数据结构

我们先回顾一下 Fiber 节点的数据结构(之前文章省略了一部分属性,所以和之前文章略有不同):


  1. function FiberNode (tag, key) { 
  2.   // 节点 key,主要用于了优化列表 diff 
  3.   this.key = key 
  4.   // 节点类型;FunctionComponent: 0, ClassComponent: 1, HostRoot: 3 ... 
  5.   this.tag = tag 
  6.  
  7.  // 子节点 
  8.   this.child = null 
  9.   // 父节点 
  10.   this.return = null  
  11.   // 兄弟节点 
  12.   this.sibling = null 
  13.    
  14.   // 更新队列,用于暂存 setState 的值 
  15.   this.updateQueue = null 
  16.   // 新传入的 props 
  17.   this.pendingProps = pendingProps; 
  18.   // 之前的 props 
  19.   this.memoizedProps = null
  20.   // 之前的 state 
  21.   this.memoizedState = null
  22.  
  23.   // 节点更新过期时间,用于时间分片 
  24.   // react 17 改为:lanes、childLanes 
  25.   this.expirationTime = NoLanes 
  26.   this.childExpirationTime = NoLanes 
  27.  
  28.   // 对应到页面的真实 DOM 节点 
  29.   this.stateNode = null 
  30.   // Fiber 节点的副本,可以理解为备胎,主要用于提升更新的性能 
  31.   this.alternate = null 
  32.  
  33.   // 副作用相关,用于标记节点是否需要更新 
  34.   // 以及更新的类型:替换成新节点、更新属性、更新文本、删除…… 
  35.   this.effectTag = NoEffect 
  36.   // 指向下一个需要更新的节点 
  37.   this.nextEffect = null 
  38.   this.firstEffect = null 
  39.   this.lastEffect = null 

缓存机制

可以注意到 Fiber 节点有个 alternate 属性,该属性在节点初始化的时候默认为空(this.alternate = null)。这个节点的作用就是用来缓存之前的 Fiber 节点,更新的时候会判断 fiber.alternate 是否为空来确定当前是首次渲染还是更新。下面我们上代码:


  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3.  
  4. class App extends React.Component { 
  5.   state = { val: 0 } 
  6.   render() { 
  7.     return <div>val: { this.state.val }</div> 
  8.   } 
  9.  
  10. ReactDOM.unstable_createRoot( 
  11.   document.getElementById('root'
  12. ).render(<App />) 

在调用 createRoot 的时候,会先生成一个FiberRootNode,在 FiberRootNode 下会有个 current 属性,current 指向 RootFiber 可以理解为一个空 Fiber。后续调用的 render 方法,就是将传入的组件挂载到 FiberRootNode.current(即 RootFiber) 的空 Fiber 节点上。


  1. // 实验版本对外暴露的 createRoot 需要加上 `unstable_` 前缀 
  2. exports.unstable_createRoot = createRoot 
  3.  
  4. function createRoot(container) { 
  5.   return new ReactDOMRoot(container) 
  6. function ReactDOMRoot(container) { 
  7.   var root = new FiberRootNode() 
  8.   // createRootFiber => createFiber => return new FiberNode(tag); 
  9.   root.current = createRootFiber() // 挂载一个空的 fiber 节点 
  10.   this._internalRoot = root 
  11. ReactDOMRoot.prototype.render = function render(children) { 
  12.   var root = this._internalRoot 
  13.   var update = createUpdate() 
  14.   update.payload = { element: children } 
  15.   const rootFiber = root.current 
  16.   // update对象放到 rootFiber 的 updateQueue 中 
  17.   enqueueUpdate(rootFiber, update
  18.   // 开始更新流程 
  19.   scheduleUpdateOnFiber(rootFiber) 

render 最后调用 scheduleUpdateOnFiber 进入更新任务,该方法之前有说明,最后会通过 scheduleCallback 走 MessageChannel 消息进入下个任务队列,最后调用 performConcurrentWorkOnRoot 方法。


  1. // scheduleUpdateOnFiber 
  2. // => ensureRootIsScheduled 
  3. // => scheduleCallback(performConcurrentWorkOnRoot) 
  4. function performConcurrentWorkOnRoot(root) { 
  5.   renderRootConcurrent(root) 
  6. function renderRootConcurrent(root) { 
  7.   // workInProgressRoot 为空,则创建 workInProgress 
  8.   if (workInProgressRoot !== root) { 
  9.     createWorkInProgress() 
  10.   } 
  11. function createWorkInProgress() { 
  12.   workInProgressRoot = root 
  13.   var current = root.current 
  14.   var workInProgress = current.alternate; 
  15.   if (workInProgress === null) { 
  16.     // 第一次构建,需要创建副本 
  17.     workInProgress = createFiber(current.tag) 
  18.     workInProgress.alternate = current 
  19.     current.alternate = workInProgress 
  20.   } else { 
  21.     // 更新过程可以复用 
  22.     workInProgress.nextEffect = null 
  23.     workInProgress.firstEffect = null 
  24.     workInProgress.lastEffect = null 
  25.   } 

开始更新时,如果 workInProgress 为空会指向一个新的空 Fiber 节点,表示正在进行工作的 Fiber 节点。

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读