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
(完)