1、Fiber的含义和做用
(1)每个ReactElement
对应一个Fiber
对象javascript
(2)记录节点的各类状态
好比ClassComponent
中的state
和props
的状态就是记录在Fiber
对象上的。php
只有当Fiber
对象更新后,才会更新到ClassComponent
上的this.state
和this.props
上java
this
上的state
和props
是根据Fiber
对象的state
、props
更新的。node
这实际上也方便了ReactHooks
,由于hooks
是为FunctionalComponent
服务的。虽然FunctionalComponent
没有this
,但Fiber
上有,是能够拿到state
和props
的react
(3)串联整个应用造成树结构
每一个ReactElement
经过props.children
与其余ReactElement
连结起来git
说明:
① ReactElement
只会把子节点(props.children
)的第一个子节点当作child
节点,其他的子节点(也就是第一个子节点的兄弟节点)都是从第一个子节点开始,依次单向链接至后一个兄弟节点github
② 每一个子节点都会指向父节点(红箭头),也就是Fiber
对象的return
属性web
export type Fiber = {|
//指向该对象在Fiber节点树中的`parent`,用来在处理完该节点后返回
//即流程图上的红线
return: Fiber | null,
}
复制代码
串联过程:
① 任一 叶子 节点A
,若是有兄弟节点,则去单向向后遍历兄弟节点,最后return
到父节点
② 父节点的child
节点不是刚刚的子节点A
的话,则从child
节点遍历到A
前的节点,并再次return
到父节点
③ 该父节点执行 ①、②浏览器
根据图1举例:
好比从左下角的input
节点开始,它没有兄弟节点,则return
到父组件Input
(由于父节点有且只有一个,因此一定return
到父节点)app
Input
有兄弟节点List
,List
又有child
节点,则从child
节点日后单向遍历兄弟节点,最后return
到List
List
又return
到div
,div
的child
节点已被遍历,则return
到App
节点,App
,App
又return
到全部Fiber
对象的根对象RootFiber
对象
这样,就将整个应用遍历完了。
2、Fiber对象
源码:
// A Fiber is work on a Component that needs to be done or was done. There can
// be more than one per component.
//Fiber对应一个即将update或已经update的组件,
// 一个组件能够有一个或多个Fiber
export type Fiber = {|
// These first fields are conceptually members of an Instance. This used to
// be split into a separate type and intersected with the other Fiber fields,
// but until Flow fixes its intersection bugs, we've merged them into a
// single type.
// An Instance is shared between all versions of a component. We can easily
// break this out into a separate object to avoid copying so much to the
// alternate versions of the tree. We put this on a single object for now to
// minimize the number of objects created during the initial render.
// Tag identifying the type of fiber.
//标记不一样的组件类型
//有原生的DOM节点,有React本身的节点
tag: WorkTag,
// Unique identifier of this child.
//ReactElement里面的key
key: null | string,
// The value of element.type which is used to preserve the identity during
// reconciliation of this child.
//ReactElement.type,也就是咱们调用createElement的第一个参数
elementType: any,
// The resolved function/class/ associated with this fiber.
//异步组件resolve以后返回的内容,通常是function或class
//好比懒加载
type: any,
// The local state associated with this fiber.
//当前Fiber的状态(好比浏览器环境就是DOM节点)
//不一样类型的实例都会记录在stateNode上
//好比DOM组件对应DOM节点实例
//ClassComponent对应Class实例
//FunctionComponent没有实例,因此stateNode值为null
//state更新了或props更新了均会更新到stateNode上
stateNode: any,
// Conceptual aliases
// parent : Instance -> return The parent happens to be the same as the
// return fiber since we've merged the fiber and instance.
// Remaining fields belong to Fiber
// The Fiber to return to after finishing processing this one.
// This is effectively the parent, but there can be multiple parents (two)
// so this is only the parent of the thing we're currently processing.
// It is conceptually the same as the return address of a stack frame.
//指向该对象在Fiber节点树中的`parent`,用来在处理完该节点后返回
//即流程图上的红线
return: Fiber | null,
// Singly Linked List Tree Structure.
//单链表树结构
//指向本身的第一个子节点
child: Fiber | null,
//指向本身的兄弟结构
//兄弟节点的return指向同一个父节点
sibling: Fiber | null,
index: number,
// The ref last used to attach this node.
// I'll avoid adding an owner field for prod and model that as functions.
//ref属性
ref: null | (((handle: mixed) => void) & {_stringRef: ?string}) | RefObject,
// Input is the data coming into process this fiber. Arguments. Props.
//新的变更带来的新的props,即nextProps
pendingProps: any, // This type will be more specific once we overload the tag.
//上一次渲染完成后的props,即 props
memoizedProps: any, // The props used to create the output.
// A queue of state updates and callbacks.
//该Fiber对应的组件,所产生的update,都会放在该队列中
updateQueue: UpdateQueue<any> | null,
// The state used to create the output
//上次渲染的state,即 state
//新的state由updateQueue计算得出,并覆盖memoizedState
memoizedState: any,
// Dependencies (contexts, events) for this fiber, if it has any
//一个列表,存在该Fiber依赖的contexts,events
dependencies: Dependencies | null,
// Bitfield that describes properties about the fiber and its subtree. E.g.
// the ConcurrentMode flag indicates whether the subtree should be async-by-
// default. When a fiber is created, it inherits the mode of its
// parent. Additional flags can be set at creation time, but after that the
// value should remain unchanged throughout the fiber's lifetime, particularly
// before its child fibers are created.
//mode有conCurrentMode和strictMode
//用来描述当前Fiber和其余子树的Bitfield
//共存的模式表示这个子树是否默认是 异步渲染的
//Fiber刚被建立时,会继承父Fiber
//其余标识也能够在建立的时候被设置,可是建立以后不应被修改,特别是它的子Fiber建立以前
mode: TypeOfMode,
//如下属性是反作用
//反作用是 标记组件哪些须要更新的工具、标记组件须要执行哪些生命周期的工具
// Effect
effectTag: SideEffectTag,
// Singly linked list fast path to the next fiber with side-effects.
nextEffect: Fiber | null,
// The first and last fiber with side-effect within this subtree. This allows
// us to reuse a slice of the linked list when we reuse the work done within
// this fiber.
firstEffect: Fiber | null,
lastEffect: Fiber | null,
// Represents a time in the future by which this work should be completed.
// Does not include work found in its subtree.
//表明任务在将来的哪一个时间点 应该被完成
//不包括该Fiber的子树产生的任务
expirationTime: ExpirationTime,
// This is used to quickly determine if a subtree has no pending changes.
//快速肯定子树中是否有 update
//若是子节点有update的话,就记录应该更新的时间
childExpirationTime: ExpirationTime,
// This is a pooled version of a Fiber. Every fiber that gets updated will
// eventually have a pair. There are cases when we can clean up pairs to save
// memory if we need to.
// 在FIber树更新的过程当中,每一个Fiber都有与其对应的Fiber
//咱们称之为 current <==> workInProgress
//在渲染完成后,会交换位置
//doubleBuffer Fiber在更新后,不用再从新建立对象,
// 而是复制自身,而且二者相互复用,用来提升性能
alternate: Fiber | null,
// Time spent rendering this Fiber and its descendants for the current update.
// This tells us how well the tree makes use of sCU for memoization.
// It is reset to 0 each time we render and only updated when we don't bailout.
// This field is only set when the enableProfilerTimer flag is enabled.
actualDuration?: number,
// If the Fiber is currently active in the "render" phase,
// This marks the time at which the work began.
// This field is only set when the enableProfilerTimer flag is enabled.
actualStartTime?: number,
// Duration of the most recent render time for this Fiber.
// This value is not updated when we bailout for memoization purposes.
// This field is only set when the enableProfilerTimer flag is enabled.
selfBaseDuration?: number,
// Sum of base times for all descedents of this Fiber.
// This value bubbles up during the "complete" phase.
// This field is only set when the enableProfilerTimer flag is enabled.
treeBaseDuration?: number,
// Conceptual aliases
// workInProgress : Fiber -> alternate The alternate used for reuse happens
// to be the same as work in progress.
// __DEV__ only
_debugID?: number,
_debugSource?: Source | null,
_debugOwner?: Fiber | null,
_debugIsCurrentlyTiming?: boolean,
_debugNeedsRemount?: boolean,
// Used to verify that the order of hooks does not change between renders.
_debugHookTypes?: Array<HookType> | null,
|};
复制代码
解析:
熟悉Fiber
的含义和属性含义就能够了,以后讲React
更新的时候,还会提到它。
GitHub:
github.com/AttackXiaoJ…
3、总结
(1)Fiber
的三个做用
(2)单向遍历
(3)props.children
链接
(4)子指父
(5)doubleBuffer
(完)