FiberRoot
里面,它也会为我们去创建的一个对象叫做 Fiber
ReactElement
都会对应一个 Fiber
对象 App
|
render() return
|
div
/ \
/ \
children[0] children[1]
/ \
/ \
/ \
Input List
| \
render() return render() return
| \
input (span span span button)
-----current----->
FiberRoot RootFiber
<---stateNode----- |
|
child
|
↓
App
|
child
|
↓
|
div
/ \
/ \
child child
/ \
/ \
/ \
Input-sibling-> List
| \
child child
| \
↓ \
input span --sibling--> span --sibling--> span --sibling--> button
// A Fiber is work on a Component that needs to be done or was done. There can
// be more than one per component.
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.
tag: WorkTag, // 标记不同的组件类型,有原生dom节点的组件, 有 class component, function component, 各种各样的组件都有对应的类型
// Unique identifier of this child.
key: null | string, // ReactElement 里面的key
// The value of element.type which is used to preserve the identity during
// reconciliation of this child.
elementType: any, // ReactElement.type, 就是调用 createElement 的第一个参数
// The resolved function/class/ associated with this fiber.
type: any, // 异步组件 resolved 之后返回的内容, 一般是 function 或 class
// The local state associated with this fiber.
stateNode: any, // 跟当前Fiber相关的本地状态,在浏览器环境中就是DOM节点,对应节点实际的实例,比如 class component 对应 class 的实例, dom组件对应dom节点的实例,function component 没有实例,就没有 stateNode, 有了它在应用更新完成后,就可以把 最新的 state,props 等放到节点上
// 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.
return: Fiber | null,
// Singly Linked List Tree Structure.
child: Fiber | null,
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: null | (((handle: mixed) => void) & {_stringRef: ?string}) | RefObject, // ref 属性
// Input is the data coming into process this fiber. Arguments. Props.
pendingProps: any, // This type will be more specific once we overload the tag. // 新的变动,带来的新的 props,就存在 pendingProps 属性上
memoizedProps: any, // The props used to create the output. // 上一次更新结束之后的 props
// A queue of state updates and callbacks.
updateQueue: UpdateQueue<any> | null, // 该 Fiber 对应的组件产生的 update 会存放在这个队列里面
// The state used to create the output
memoizedState: any, // 上次渲染完成之后的 state,比如我们执行setState,会算出一个新的state,算出是要经过 updateQueue计算的, 计算完之后覆盖 memoizedState 值
// A linked-list of contexts that this fiber depends on
firstContextDependency: ContextDependency<mixed> | null, // 一个列表,存放这个Fiber依赖的context
// 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: TypeOfMode, // 用于描述当前Fiber和它子树的Bitfield, 共存的模式表示这个子树是否默认是异步渲染的, Fiber 被创建的时候会继承父Fiber, 其他的标识也可以在创建的时候被设置,但在创建之后不应该再被修改,特别是他的子Fiber创建之前, 对应比如: ConcurrentMode, StrictMode,
// Effect
effectTag: SideEffectTag, // 副作用,用来记录 Side Effect
// Singly linked list fast path to the next fiber with side-effects.
nextEffect: Fiber | null, // 副作用, 单链表用来快速查找下一个 side effect
// 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, // 副作用,子树中第一个 side effect
lastEffect: Fiber | null, // 副作用,子树中最后一个 side effect
// Represents a time in the future by which this work should be completed.
// Does not include work found in its subtree.
expirationTime: ExpirationTime, // 当前节点产生的更新任务的过期时间, 代表任务在未来的哪个时间点应该被完成,不包括他的子树产生的任务
// This is used to quickly determine if a subtree has no pending changes.
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.
alternate: Fiber | null, // 在Fiber树更新的过程中,每个Fiber都会有一个跟其对应的Fiber,我们称它为 current <==> workInProgress的对应关系, 在渲染完成之后他们会交换位置,在更新过程中,会根据整个Fiber对象,创建一个 workInProgress, current是当前的, workInProgress 是要进行一个更新的, 在更新完成后,workInProgress 状态会更新成一个新的,current就变成老的,最终节点渲染到 dom 上面,workInProgress 会变成current,再下一次更新到来的时候,会保持着两个对象都存在,这个在 react 中叫做 double buffer, 是用来提高性能的
// 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,
|};
return
, child
, sibling
可以帮助把应用中的所有节点一一串联
return
: 指向它在Fiber节点树中的 parent, 用来处理完这个节点之后,向上返回child
: 单链表树结构, 指向自己的第一个子节点sibling
: 指向自己的兄弟结构,兄弟节点的return指向同一个父节点