Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React16.2源码解析-Fiber架构 #11

Open
UNDERCOVERj opened this issue Jun 3, 2018 · 0 comments
Open

React16.2源码解析-Fiber架构 #11

UNDERCOVERj opened this issue Jun 3, 2018 · 0 comments

Comments

@UNDERCOVERj
Copy link
Owner

UNDERCOVERj commented Jun 3, 2018

什么是fiber

所谓fiber,它其实是一个react中的架构,一个 fiber 对象代表了一个work单位

优化渲染任务,让一个大组件细化,从同步变成异步,让渲染任务有了优先级。生命周期函数调用不再是同步的,让用户能感知的性能提高了。

fiber可以把很大的工作分成一个个小块(trunk),trunk之间是异步的,每个trunk之间可以执行别的操作。

render函数为界,分为两个阶段,在render之前改变 workInProgress tree,执行生命周期函数比如componentWillMountcomponentWillReceiveProp。在render函数之后,执行componentDidMountcomponentDidUpdate。在第一个阶段,可能被中断。

优势

  1. 当处理 ui 时,如果很多 work 突然运行,可以使动画帧下降。fiber 被视为 virtual stack frame ,能定制调用栈优化行为,并能随意中断调用堆栈和手动操作堆栈帧。

特性

  1. 在更新过程中能暂停、中断、重用 work
  2. 为更新队列安排优先级
  3. 异步基元

结构

fiber是一个JavaScript对象,其中包含组件及组件的输入输出等信息,它也对应于一个组件的一个实例

图解 fiber 对象

image

fiber的属性及意义

  1. typetagkey

fibertypekey就像它们在React 元素中的作用一样。

type描述它对应的组件,可为 f App() {},'div'等。typeClassComponent 创建实例时能用到

var ctor = workInProgress.type;
var instance = new ctor(props, context);

tagtype 对应组件类型的值可以为构造函数(FunctionalComponent)或类组件(ClassComponent)或者html 标签 HostComponent

keyreconciliation 阶段决定如何重用 fiber

  1. childsibling

childSibiling

这两个属性指向其他fiber,描述一个fiber的递归树结构

child对应一个 fiber.props.children 中的第一个 childFiber

render方法返回的多元children时,child形成一个list,头指针指向第一个孩子fiber 节点,则childsibling就是第一个孩子fiber 几点的兄弟 fiber 节点

function Parent() {
  return [<Child1 />, <Child2 />]
}

以上代码,ParentchildChild1Child1sibling就为Child2

  1. return

return fiber是处理workInProgress后返回的fiber,被视为parent fiber

  1. pendingPropsmemoizedProps

props是应一个函数的参数。在fiber中,pendingProps在它执行之前被设置, memoizedProps在它执行之后被设置

当即将到来的pendingPropsmemoizedProps相同,标志着fiber之前的输出能被重用,避免了不必要的工作

  1. alternate

work-in-progress阶段:fiber 只是current fiber 的代替物

current fiberalternateworkInProgressworkInProgressalternatecurrent

  1. stateNode

image

fiberRootstateNode指向root,是一个循环对象,在root.current.alternate下的fiber中的stateNode则是每个fiber对应的dom或者 instance

fiber与dom及instance的对应关系

image

  1. 如何从 dom 中找到 fiber

dom 元素中有以 __reactInternalInstance 开头的属性,此属性即指向dom 对应的 fiber

var internalInstanceKey = '__reactInternalInstance$' + randomKey;

function getInstanceFromNode$1(node) {
    var inst = node[internalInstanceKey];
    if (inst) {
        if (inst.tag === HostComponent || inst.tag === HostText) {
            return inst;
        } else {
            return null;
        }
    }
    return null;
}
  1. 如何从组件的实例中取得 fiber

从思维导图中可以看到,如果stateNode 为组件实例 instance ,则其中有_reactInternalFiber 属性,指向该组件的 fiber

function get(key) { // 得到instance的fiber
    return key._reactInternalFiber;
}
  1. 如何得到fiber对应的dom

如果fiber.tag === HostComponent,即fiberdiv、spanhtml 元素类型,则该fiberstateNode指向的就是具体的 dom节点

如何创建fiber

创建fiber

创建时 fibertag 有如下 11 种类型

var IndeterminateComponent = 0; // Before we know whether it is functional or class
var FunctionalComponent = 1;
var ClassComponent = 2;
var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
var HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
var HostComponent = 5;
var HostText = 6;
var CallComponent = 7;
var CallHandlerPhase = 8;
var ReturnComponent = 9;
var Fragment = 10;

最基础的创建 fiber 的方法是 createFiber ,传入 tag、key、internalContextTag,返回 FiberNode 实例

reference

  1. https://github.com/acdlite/react-fiber-architecture
  2. https://tech.youzan.com/react-fiber/
@UNDERCOVERj UNDERCOVERj changed the title React16.2品析-Fiber架构 React16.2最新源码解析-Fiber架构 Jun 4, 2018
@UNDERCOVERj UNDERCOVERj changed the title React16.2最新源码解析-Fiber架构 React16.2源码解析-Fiber架构 Jun 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant