摘要:一的含義和作用每一個(gè)對(duì)應(yīng)一個(gè)對(duì)象記錄節(jié)點(diǎn)的各種狀態(tài)比如中的和的狀態(tài)就是記錄在對(duì)象上的。只有當(dāng)對(duì)象更新后,才會(huì)更新到上的和上上的和是根據(jù)對(duì)象的更新的。
一、Fiber的含義和作用
(1)每一個(gè)ReactElement對(duì)應(yīng)一個(gè)Fiber對(duì)象
(2)記錄節(jié)點(diǎn)的各種狀態(tài)
比如ClassComponent中的state和props的狀態(tài)就是記錄在Fiber對(duì)象上的。
只有當(dāng)Fiber對(duì)象更新后,才會(huì)更新到ClassComponent上的this.state和this.props上
this上的state和props是根據(jù)Fiber對(duì)象的state、props更新的。
這實(shí)際上也方便了ReactHooks,因?yàn)?b>hooks是為FunctionalComponent服務(wù)的。雖然FunctionalComponent沒(méi)有this,但Fiber上有,是可以拿到state和props的
(3)串聯(lián)整個(gè)應(yīng)用形成樹結(jié)構(gòu)
每個(gè)ReactElement通過(guò)props.children與其他ReactElement連結(jié)起來(lái)
說(shuō)明:
① ReactElement只會(huì)把子節(jié)點(diǎn)(props.children)的第一個(gè)子節(jié)點(diǎn)當(dāng)做child節(jié)點(diǎn),其余的子節(jié)點(diǎn)(也就是第一個(gè)子節(jié)點(diǎn)的兄弟節(jié)點(diǎn))都是從第一個(gè)子節(jié)點(diǎn)開始,依次單向連接至后一個(gè)兄弟節(jié)點(diǎn)
② 每個(gè)子節(jié)點(diǎn)都會(huì)指向父節(jié)點(diǎn)(紅箭頭),也就是Fiber對(duì)象的return屬性
export type Fiber = {| //指向該對(duì)象在Fiber節(jié)點(diǎn)樹中的`parent`,用來(lái)在處理完該節(jié)點(diǎn)后返回 //即流程圖上的紅線 return: Fiber | null, }
串聯(lián)過(guò)程:
① 任一 葉子 節(jié)點(diǎn)A,如果有兄弟節(jié)點(diǎn),則去單向向后遍歷兄弟節(jié)點(diǎn),最后return到父節(jié)點(diǎn)
② 父節(jié)點(diǎn)的child節(jié)點(diǎn)不是剛剛的子節(jié)點(diǎn)A的話,則從child節(jié)點(diǎn)遍歷到A前的節(jié)點(diǎn),并再次return到父節(jié)點(diǎn)
③ 該父節(jié)點(diǎn)執(zhí)行 ①、②
根據(jù)圖1舉例:
比如從左下角的input節(jié)點(diǎn)開始,它沒(méi)有兄弟節(jié)點(diǎn),則return到父組件Input(因?yàn)楦腹?jié)點(diǎn)有且只有一個(gè),所以必定return到父節(jié)點(diǎn))
Input有兄弟節(jié)點(diǎn)List,List又有child節(jié)點(diǎn),則從child節(jié)點(diǎn)往后單向遍歷兄弟節(jié)點(diǎn),最后return到List
List又return到div,div的child節(jié)點(diǎn)已被遍歷,則return到App節(jié)點(diǎn),App,App又return到所有Fiber對(duì)象的根對(duì)象RootFiber對(duì)象
這樣,就將整個(gè)應(yīng)用遍歷完了。
二、Fiber對(duì)象
源碼:
// A Fiber is work on a Component that needs to be done or was done. There can // be more than one per component. //Fiber對(duì)應(yīng)一個(gè)即將update或已經(jīng)update的組件, // 一個(gè)組件可以有一個(gè)或多個(gè)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. //標(biāo)記不同的組件類型 //有原生的DOM節(jié)點(diǎn),有React自己的節(jié)點(diǎn) 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,也就是我們調(diào)用createElement的第一個(gè)參數(shù) elementType: any, // The resolved function/class/ associated with this fiber. //異步組件resolve之后返回的內(nèi)容,一般是function或class //比如懶加載 type: any, // The local state associated with this fiber. //當(dāng)前Fiber的狀態(tài)(比如瀏覽器環(huán)境就是DOM節(jié)點(diǎn)) //不同類型的實(shí)例都會(huì)記錄在stateNode上 //比如DOM組件對(duì)應(yīng)DOM節(jié)點(diǎn)實(shí)例 //ClassComponent對(duì)應(yīng)Class實(shí)例 //FunctionComponent沒(méi)有實(shí)例,所以stateNode值為null //state更新了或props更新了均會(huì)更新到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. //指向該對(duì)象在Fiber節(jié)點(diǎn)樹中的`parent`,用來(lái)在處理完該節(jié)點(diǎn)后返回 //即流程圖上的紅線 return: Fiber | null, // Singly Linked List Tree Structure. //單鏈表樹結(jié)構(gòu) //指向自己的第一個(gè)子節(jié)點(diǎn) child: Fiber | null, //指向自己的兄弟結(jié)構(gòu) //兄弟節(jié)點(diǎn)的return指向同一個(gè)父節(jié)點(diǎn) 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. //新的變動(dòng)帶來(lái)的新的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對(duì)應(yīng)的組件,所產(chǎn)生的update,都會(huì)放在該隊(duì)列中 updateQueue: UpdateQueue| null, // The state used to create the output //上次渲染的state,即 state //新的state由updateQueue計(jì)算得出,并覆蓋memoizedState memoizedState: any, // Dependencies (contexts, events) for this fiber, if it has any //一個(gè)列表,存在該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 //用來(lái)描述當(dāng)前Fiber和其他子樹的Bitfield //共存的模式表示這個(gè)子樹是否默認(rèn)是 異步渲染的 //Fiber剛被創(chuàng)建時(shí),會(huì)繼承父Fiber //其他標(biāo)識(shí)也可以在創(chuàng)建的時(shí)候被設(shè)置,但是創(chuàng)建之后不該被修改,特別是它的子Fiber創(chuàng)建之前 mode: TypeOfMode, //以下屬性是副作用 //副作用是 標(biāo)記組件哪些需要更新的工具、標(biāo)記組件需要執(zhí)行哪些生命周期的工具 // 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. //代表任務(wù)在未來(lái)的哪個(gè)時(shí)間點(diǎn) 應(yīng)該被完成 //不包括該Fiber的子樹產(chǎn)生的任務(wù) expirationTime: ExpirationTime, // This is used to quickly determine if a subtree has no pending changes. //快速確定子樹中是否有 update //如果子節(jié)點(diǎn)有update的話,就記錄應(yīng)該更新的時(shí)間 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樹更新的過(guò)程中,每個(gè)Fiber都有與其對(duì)應(yīng)的Fiber //我們稱之為 current <==> workInProgress //在渲染完成后,會(huì)交換位置 //doubleBuffer Fiber在更新后,不用再重新創(chuàng)建對(duì)象, // 而是復(fù)制自身,并且兩者相互復(fù)用,用來(lái)提高性能 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 | null, |};
解析:
熟悉Fiber的含義和屬性含義就可以了,之后講React更新的時(shí)候,還會(huì)提到它。
GitHub:
https://github.com/AttackXiaoJinJin/reactExplain/blob/master/react16.8.6/packages/react-reconciler/src/ReactFiber.js
三、總結(jié)
(1)Fiber的三個(gè)作用
(2)單向遍歷
(3)props.children連接
(4)子指父
(5)doubleBuffer
(完)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/110000.html
摘要:查看創(chuàng)建核心函數(shù)源碼行調(diào)用函數(shù)創(chuàng)建是相關(guān),不用管源碼行這個(gè)指的是調(diào)用創(chuàng)建,下面我們將會(huì)說(shuō)到對(duì)象源碼行源碼行函數(shù)中,首先創(chuàng)建了一個(gè),然后又創(chuàng)建了一個(gè),它們兩者還是相互引用。 感謝 yck: 剖析 React 源碼解析,本篇文章是在讀完他的文章的基礎(chǔ)上,將他的文章進(jìn)行拆解和加工,加入我自己的一下理解和例子,便于大家理解。覺得yck寫的真的很棒 。React 版本為 16.8.6,關(guān)于源碼的...
摘要:一更新的方式有三種渲染接下來(lái),我們就來(lái)看下源碼二作用在提供的里渲染一個(gè)元素,并返回對(duì)該組件的引用常見的用法是這個(gè)官網(wǎng)網(wǎng)址源碼服務(wù)端使用方法渲染節(jié)點(diǎn)是讓服務(wù)端盡可能復(fù)用節(jié)點(diǎn),提高性能元素容器應(yīng)用渲染結(jié)束后,調(diào)用的函數(shù)錯(cuò)誤抓取方法本質(zhì)是返回 showImg(https://segmentfault.com/img/remote/1460000020064414?w=1240&h=641);...
摘要:是整個(gè)應(yīng)用的起點(diǎn),包含應(yīng)用掛載的目標(biāo)節(jié)點(diǎn),記錄整個(gè)應(yīng)用更新過(guò)程的各種信息是一個(gè)對(duì)象是當(dāng)前應(yīng)用對(duì)應(yīng)的對(duì)象,即。每個(gè)節(jié)點(diǎn)會(huì)對(duì)應(yīng)一個(gè)對(duì)象,記錄節(jié)點(diǎn)的各種狀態(tài),比如,,這些狀態(tài)更新完成后會(huì)被更新,是所對(duì)應(yīng)節(jié)點(diǎn)的實(shí)際的實(shí)例,比如對(duì)應(yīng)一個(gè)就是一個(gè)。 ReactDom.render做了什么 首先react代碼分為react和react-dom兩個(gè)包,react中代碼量特別的少,基本就是API的定義,...
摘要:大家可以看到是構(gòu)造函數(shù)構(gòu)造出來(lái)的,并且內(nèi)部有一個(gè)對(duì)象,這個(gè)對(duì)象是本文接下來(lái)要重點(diǎn)介紹的對(duì)象,接下來(lái)我們就來(lái)一窺究竟吧。在構(gòu)造函數(shù)內(nèi)部就進(jìn)行了一步操作,那就是創(chuàng)建了一個(gè)對(duì)象,并掛載到了上。下一篇文章還是流程相關(guān)的內(nèi)容。這是我的剖析 React 源碼的第二篇文章,如果你沒(méi)有閱讀過(guò)之前的文章,請(qǐng)務(wù)必先閱讀一下 第一篇文章 中提到的一些注意事項(xiàng),能幫助你更好地閱讀源碼。 文章相關(guān)資料 React ...
摘要:因?yàn)榘姹緦⒄嬲龔U棄這三生命周期到目前為止,的渲染機(jī)制遵循同步渲染首次渲染,更新時(shí)更新時(shí)卸載時(shí)期間每個(gè)周期函數(shù)各司其職,輸入輸出都是可預(yù)測(cè),一路下來(lái)很順暢。通過(guò)進(jìn)一步觀察可以發(fā)現(xiàn),預(yù)廢棄的三個(gè)生命周期函數(shù)都發(fā)生在虛擬的構(gòu)建期間,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段時(shí)間準(zhǔn)備前端招聘事項(xiàng)...
閱讀 2943·2023-04-25 19:08
閱讀 1428·2021-11-16 11:45
閱讀 1991·2021-10-13 09:40
閱讀 4160·2021-09-30 09:47
閱讀 2425·2019-08-30 15:44
閱讀 2302·2019-08-30 13:03
閱讀 1401·2019-08-30 12:56
閱讀 1901·2019-08-26 14:04