中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

玉林網(wǎng)站制作想做百度推廣找誰(shuí)

玉林網(wǎng)站制作,想做百度推廣找誰(shuí),網(wǎng)站載入頁(yè)面怎么做,wordpress百家completeUnitOfWork 1 )概述 各種不同類(lèi)型組件的一個(gè)更新過(guò)程對(duì)應(yīng)的是在執(zhí)行 performUnitOfWork 里面的 beginWork 階段它是去向下遍歷一棵 fiber 樹(shù)的一側(cè)的子節(jié)點(diǎn),然后遍歷到葉子節(jié)點(diǎn)為止,以及 return 自己 child 的這種方式在 performUni…

completeUnitOfWork


1 )概述

  • 各種不同類(lèi)型組件的一個(gè)更新過(guò)程對(duì)應(yīng)的是在執(zhí)行 performUnitOfWork 里面的 beginWork 階段
  • 它是去向下遍歷一棵 fiber 樹(shù)的一側(cè)的子節(jié)點(diǎn),然后遍歷到葉子節(jié)點(diǎn)為止,以及 return 自己 child 的這種方式
  • performUnitOfWork 里面,還有一個(gè)方法叫做 completeUnitOfWork
  • completeUnitOfWork 中會(huì)根據(jù)是否有中斷,調(diào)用不同的一個(gè)處理方法
  • 什么叫中斷呢?
    • 就是我們?cè)阡秩疽粋€(gè)組件的時(shí)候,出現(xiàn)了錯(cuò)誤的場(chǎng)景進(jìn)行處理
    • 或者優(yōu)先級(jí)被更高優(yōu)先級(jí)打斷,低優(yōu)先級(jí)轉(zhuǎn)移到下一次處理
  • renderRoot 當(dāng)中, 使用try catch去調(diào)用 workLoop 去循環(huán)每一個(gè)節(jié)點(diǎn)的
  • workLoop 里面調(diào)用的就是 performUnitOfWork
  • performUnitOfWork 里面調(diào)用了 beginWork
  • 它里面就是執(zhí)行各種不同組件的一個(gè)update的一個(gè)過(guò)程
  • 在后面 completeUnitOfWork ,是處理到一側(cè)的子節(jié)點(diǎn)遍歷到最下層的時(shí)候,它沒(méi)有子節(jié)點(diǎn)可以返回了
  • 因?yàn)?beginWork 里面調(diào)用了各種update,它們都是return自己的child
  • 比如說(shuō),有這么一棵 fiber 樹(shù)的一個(gè)情況的時(shí)候
  • 我們先去對(duì) RootFiber 執(zhí)行了 beginWork,然后執(zhí)行了之后 return 的是它的 child,也就是 App
  • 一層一層這么執(zhí)行下來(lái)之后,到了有分叉節(jié)點(diǎn),也就是說(shuō)一個(gè)節(jié)點(diǎn),下面有多個(gè)子節(jié)點(diǎn)的情況
  • 它 return 的還是它的第一個(gè) child 節(jié)點(diǎn),所以這個(gè)時(shí)候,后面的節(jié)點(diǎn)是沒(méi)有被執(zhí)行到更新的
  • 因?yàn)?inpput 它返回了之后,返回的是它里面的 input child 這個(gè)節(jié)點(diǎn)
  • 到這里為止,這個(gè) dom 的 input 節(jié)點(diǎn),已經(jīng)沒(méi)有child了,這個(gè)時(shí)候就 return null
  • 因?yàn)樗?child是 null,所以在這里首先執(zhí)行的是 beginWork
  • 如果有child,它就會(huì)一直往child方向進(jìn)行一個(gè)查找
  • 等到 next 等于 null 的情況的時(shí)候,就會(huì)去執(zhí)行 completeUnitOfWork
  • completeUnitOfWork 就是對(duì)當(dāng)前這個(gè)input界定 執(zhí)行它的complete,具體執(zhí)行什么
  • beginWork 的過(guò)程當(dāng)中,如果我們?nèi)pdate某一個(gè)節(jié)點(diǎn)的時(shí)候,有報(bào)錯(cuò)了
  • 或者是 throw 了一個(gè) promise, 就是 suspend 的情況, 它會(huì)執(zhí)行一定的標(biāo)記
  • renderRoot 當(dāng)中,我們可以看到它如果有報(bào)錯(cuò),它的catch是要在 renderRoot 里面被捕獲的這個(gè)錯(cuò)誤
  • 對(duì)這個(gè)錯(cuò)誤補(bǔ)獲之后,它是有一定的處理的, 處理完之后,它仍然處于這個(gè) while 循環(huán)當(dāng)中,它里面并沒(méi)有 break
    • 位置: packages/react-reconciler/src/ReactFiberScheduler.js#L1276
  • 這個(gè)時(shí)候它還是會(huì)往下進(jìn)行一個(gè)執(zhí)行的,只不過(guò)它會(huì)在里面給我們當(dāng)前這個(gè)節(jié)點(diǎn)去執(zhí)行一個(gè)標(biāo)記
  • completeUnitOfWork 的階段,會(huì)對(duì)有各種不同標(biāo)記的一個(gè)節(jié)點(diǎn),執(zhí)行不同的方法
  • 主要的是我們正常流程走的是叫 completeWork 這么一個(gè)方法
  • 而對(duì)于有異常的節(jié)點(diǎn),它的一個(gè)流程是調(diào)用一個(gè)叫 unwindWork 的方法
  • 然后會(huì)判斷是否有兄弟節(jié)點(diǎn)來(lái)執(zhí)行不同的操作
    • 比如執(zhí)行到上圖 input 這個(gè)節(jié)點(diǎn)的 completeUnitOfWork之后,它沒(méi)有兄弟節(jié)點(diǎn)
    • 它直接去執(zhí)行它的父節(jié)點(diǎn),也就是 Input 組件的 completeUnitOfWork
    • 在這里,我們發(fā)現(xiàn)它是有兄弟節(jié)點(diǎn)的,因?yàn)榈谝淮蝩pdate的過(guò)程,是往下的
    • 對(duì)于旁邊的 List 節(jié)點(diǎn)是沒(méi)有任何更新的, 這個(gè)時(shí)候我們就會(huì)返回它的兄弟節(jié)點(diǎn) List
  • 對(duì)于這個(gè)兄弟節(jié)點(diǎn), 繼續(xù)對(duì)它執(zhí)行一個(gè)update的一個(gè)過(guò)程,也就是 beginWork 的一個(gè)過(guò)程
  • 這就是在 completeUnitOfWork 里面非常重要的一個(gè)判斷條件
    • 就是如果有兄弟節(jié)點(diǎn),它會(huì)直接返回這個(gè)兄弟節(jié)點(diǎn)
  • 完成節(jié)點(diǎn)之后要賦值整個(gè)effect鏈
    • effect是非常重要的,后面即將要把所有的更新結(jié)束的節(jié)點(diǎn),掛載到真正的dom上面
    • 這一個(gè)階段叫做commit階段,它要去執(zhí)行每一個(gè)節(jié)點(diǎn)不同的跟dom有關(guān)的操作
    • 在前面 beginWorkcompleteUnitOfWork,對(duì)每一個(gè)節(jié)點(diǎn)的更新過(guò)程標(biāo)記了
    • 有哪些 SideEffect 最終要被commit的一個(gè)過(guò)程
    • completeUnitOfWork 里面會(huì)完成這一步,把所有的effect節(jié)點(diǎn)進(jìn)行一個(gè)串聯(lián)
    • commitWork 的階段可以非常方便的根據(jù)這個(gè)鏈去執(zhí)行每一個(gè)節(jié)點(diǎn)的最終的操作

2 ) 源碼

定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L939
找到 completeUnitOfWork

// 這個(gè)API 是在 workInProgress 的基礎(chǔ)上進(jìn)行的一個(gè)操作
function completeUnitOfWork(workInProgress: Fiber): Fiber | null {// Attempt to complete the current unit of work, then move to the// next sibling. If there are no more siblings, return to the// parent fiber.// 進(jìn)來(lái)首先就是一個(gè) while true 的一個(gè)循環(huán)while (true) {// The current, flushed, state of this fiber is the alternate.// Ideally nothing should rely on this, but relying on it here// means that we don't need an additional field on the work in// progress.// 對(duì)于這個(gè)循環(huán), 它首先獲取currentconst current = workInProgress.alternate;if (__DEV__) {ReactCurrentFiber.setCurrentFiber(workInProgress);}// 然后 獲取 returnFiber 和 siblingFiber,也就是它的父節(jié)點(diǎn)以及它的兄弟節(jié)點(diǎn)// 這個(gè)在后面我們判斷是否要返回兄弟節(jié)點(diǎn)的時(shí)候就會(huì)用到const returnFiber = workInProgress.return;const siblingFiber = workInProgress.sibling;// 這里首先一進(jìn)來(lái)就有一個(gè)大的判斷,它是一個(gè)整個(gè)方法里面最大的一個(gè)判斷// Incomplete 就是這個(gè)節(jié)點(diǎn)它是出現(xiàn)了錯(cuò)誤,然后被捕獲的, 并標(biāo)記這個(gè) sideEffect// 邏輯與操作來(lái)判斷某一個(gè)屬性上面它是否有某一個(gè)特性的一個(gè)方式if ((workInProgress.effectTag & Incomplete) === NoEffect) {if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {// Don't replay if it fails during completion phase.mayReplayFailedUnitOfWork = false;}// This fiber completed.// Remember we're completing this unit so we can find a boundary if it fails.nextUnitOfWork = workInProgress;if (enableProfilerTimer) {if (workInProgress.mode & ProfileMode) {startProfilerTimer(workInProgress);}nextUnitOfWork = completeWork(current,workInProgress,nextRenderExpirationTime,);if (workInProgress.mode & ProfileMode) {// Update render duration assuming we didn't error.stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);}} else {nextUnitOfWork = completeWork(current,workInProgress,nextRenderExpirationTime,);}if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {// We're out of completion phase so replaying is fine now.mayReplayFailedUnitOfWork = true;}stopWorkTimer(workInProgress);resetChildExpirationTime(workInProgress, nextRenderExpirationTime);if (__DEV__) {ReactCurrentFiber.resetCurrentFiber();}if (nextUnitOfWork !== null) {// Completing this fiber spawned new work. Work on that next.return nextUnitOfWork;}// 接下去這個(gè)個(gè)判斷,是要構(gòu)造一個(gè)所有 有 SideEffect 的節(jié)點(diǎn)的一個(gè)鏈狀的結(jié)構(gòu)// 這個(gè)鏈狀結(jié)構(gòu)最終是用于 commitWork 的時(shí)候用來(lái)進(jìn)行對(duì)這些有 SideEffect的節(jié)點(diǎn)進(jìn)行 commit 的一個(gè)操作,// 這邊它的一個(gè)判斷條件,returnFiber不等于null,并且returnFiber它不是一個(gè) Incomplete 的一個(gè)節(jié)點(diǎn)// 因?yàn)閷?duì)于一個(gè) Incomplete 的節(jié)點(diǎn),它唯一可以具有的一個(gè)SideEffect,就是這個(gè)節(jié)點(diǎn)已經(jīng)被捕獲了// 因?yàn)閷?duì)于有 Incomplete 錯(cuò)誤的節(jié)點(diǎn)是不會(huì)渲染正常的子節(jié)點(diǎn)的if (returnFiber !== null &&// Do not append effects to parents if a sibling failed to complete(returnFiber.effectTag & Incomplete) === NoEffect) {// Append all the effects of the subtree and this fiber onto the effect// list of the parent. The completion order of the children affects the// side-effect order.// 對(duì)于正常的一個(gè)情況, 首先要判斷一下 returnFiber.firstEffect 是否等于 null// 符合判斷就代表 現(xiàn)在這個(gè) returnFiber 上還沒(méi)有記錄任何它的子節(jié)點(diǎn)的有副作用的子節(jié)點(diǎn)// 這個(gè)時(shí)候, 直接把當(dāng)前節(jié)點(diǎn)的firstEffect賦值給 returnFiber.firstEffect// 因?yàn)樗笆菦](méi)有任何一個(gè)的嘛,我們這邊真正要做的是把當(dāng)前節(jié)點(diǎn)的 firstEffect 到 lastEffect的一個(gè)鏈條// 這個(gè)單項(xiàng)鏈表,給它掛載到它的父節(jié)點(diǎn)的同樣的一個(gè) firstEffect到lastEffect的單項(xiàng)鏈表的最后if (returnFiber.firstEffect === null) {returnFiber.firstEffect = workInProgress.firstEffect;}// 就是下面這一段判斷,就是來(lái)做這個(gè)事情的, 如果returnFiber.lastEffect不等于null,那說(shuō)明它已經(jīng)有了// 那么對(duì)于returnFiber上面有記錄過(guò)別的 SideEffect 的節(jié)點(diǎn)之后// 我們當(dāng)前節(jié)點(diǎn)是掛載到整個(gè) SideEffect 鏈的最后,就是下面這樣,就是把它連到最后的上面if (workInProgress.lastEffect !== null) {if (returnFiber.lastEffect !== null) {returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;}// 還要操作如下,因?yàn)樗倪@個(gè)(returnFiber.lastEffect)指針目前還指向它原來(lái)的那個(gè)lastEffect// 在 賦值 nextEffect之后,它的最后一個(gè)就是這個(gè)鏈的最后一個(gè)已經(jīng)變成 workInProgress.lastEffect,所以這邊要執(zhí)行這么一個(gè)操作// 當(dāng)然這個(gè)條件是要建立在 workInProgress.lastEffect 是有值的情況// 這是把它們各自的firsteffect到lasteffect,這個(gè)鏈給它進(jìn)行一個(gè)串聯(lián)的過(guò)程returnFiber.lastEffect = workInProgress.lastEffect;}// If this fiber had side-effects, we append it AFTER the children's// side-effects. We can perform certain side-effects earlier if// needed, by doing multiple passes over the effect list. We don't want// to schedule our own side-effect on our own list because if end up// reusing children we'll schedule this effect onto itself since we're// at the end.// 對(duì)于returnFiber來(lái)說(shuō),當(dāng)前這個(gè)節(jié)點(diǎn)也可能是有副作用的,那么這邊就接下去就會(huì)做這個(gè)操作// 如果當(dāng)前節(jié)點(diǎn)的 effectTag  > PerformedWork 的,因?yàn)?PerformedWork 是一個(gè)給 DEVTool 用的一個(gè) sideEffect// 對(duì)于真正的react更新是沒(méi)有任何意義的, 所以如果它僅僅只有 PerformedWork ,它就不是一個(gè)有效的 SideEffect 的節(jié)點(diǎn)const effectTag = workInProgress.effectTag;// Skip both NoWork and PerformedWork tags when creating the effect list.// PerformedWork effect is read by React DevTools but shouldn't be committed.if (effectTag > PerformedWork) {// 如果它有 SideEffect,就把當(dāng)前節(jié)點(diǎn)作為父節(jié)點(diǎn)的 SideEffect 鏈的最后一個(gè)給它掛載上去// 或者如果是當(dāng)前父節(jié)點(diǎn)沒(méi)有任何記錄的 SideEffect,它就是第一個(gè)if (returnFiber.lastEffect !== null) {returnFiber.lastEffect.nextEffect = workInProgress;} else {returnFiber.firstEffect = workInProgress;}returnFiber.lastEffect = workInProgress;}}if (__DEV__ && ReactFiberInstrumentation.debugTool) {ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);}if (siblingFiber !== null) {// If there is more work to do in this returnFiber, do that next.return siblingFiber;} else if (returnFiber !== null) {// If there's no more work in this returnFiber. Complete the returnFiber.workInProgress = returnFiber;continue;} else {// We've reached the root.return null;}} else {if (enableProfilerTimer && workInProgress.mode & ProfileMode) {// Record the render duration for the fiber that errored.stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);// Include the time spent working on failed children before continuing.let actualDuration = workInProgress.actualDuration;let child = workInProgress.child;while (child !== null) {actualDuration += child.actualDuration;child = child.sibling;}workInProgress.actualDuration = actualDuration;}// This fiber did not complete because something threw. Pop values off// the stack without entering the complete phase. If this is a boundary,// capture values if possible.const next = unwindWork(workInProgress, nextRenderExpirationTime);// Because this fiber did not complete, don't reset its expiration time.if (workInProgress.effectTag & DidCapture) {// Restarting an error boundarystopFailedWorkTimer(workInProgress);} else {stopWorkTimer(workInProgress);}if (__DEV__) {ReactCurrentFiber.resetCurrentFiber();}if (next !== null) {stopWorkTimer(workInProgress);if (__DEV__ && ReactFiberInstrumentation.debugTool) {ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);}// If completing this work spawned new work, do that next. We'll come// back here again.// Since we're restarting, remove anything that is not a host effect// from the effect tag.next.effectTag &= HostEffectMask;return next;}if (returnFiber !== null) {// Mark the parent fiber as incomplete and clear its effect list.returnFiber.firstEffect = returnFiber.lastEffect = null;returnFiber.effectTag |= Incomplete;}if (__DEV__ && ReactFiberInstrumentation.debugTool) {ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);}// 存在 sibling 節(jié)點(diǎn), 注意這邊是return,也就是跳出while循環(huán)if (siblingFiber !== null) {// If there is more work to do in this returnFiber, do that next.return siblingFiber;} else if (returnFiber !== null) {// If there's no more work in this returnFiber. Complete the returnFiber.// 如果returnFiber不等于null,那么 workInProgress = returnFiber// 比如對(duì)于最上面示例圖的 input節(jié)點(diǎn),它的 completeUnitOfWork// 如果它沒(méi)有兄弟節(jié)點(diǎn),那么它就繼續(xù)執(zhí)行Input的 completeUnitOfWork// 這個(gè)循環(huán)是在 completeUnitOfWork 內(nèi)部進(jìn)行的一個(gè)過(guò)程workInProgress = returnFiber;continue;} else {// 如果 returnFiber 也等于null,那么它直接 return null// 說(shuō)明已經(jīng)到達(dá)頂點(diǎn)了,就到達(dá) RootFiber 了,我們的更新過(guò)程呢已經(jīng)完成了// 只需要在接下去 commitRoot 就可以了return null;}}}// Without this explicit null return Flow complains of invalid return type// TODO Remove the above while(true) loop// eslint-disable-next-line no-unreachablereturn null;
}
  • 對(duì)于這個(gè)while循環(huán)里面,其實(shí)它的所有代碼都是在if else里面的
  • if else它們最大的一個(gè)區(qū)別是什么呢?
    • 在if里面我們可以看這邊這個(gè)特殊情況
    • 就是 nextUnitOfWork 等于 completeWork,然后傳入一些屬性
    • 對(duì)于 else 的情況,這邊調(diào)用了 next = unwindWork
    • 這就是對(duì)于一個(gè)是否有拋出過(guò)錯(cuò)誤的一個(gè)節(jié)點(diǎn),執(zhí)行的一個(gè)不同的操作
  • completeWork,是沒(méi)有任何一個(gè)錯(cuò)誤的一個(gè)節(jié)點(diǎn),它的一個(gè)complete的一個(gè)過(guò)程
    • 調(diào)用了completework,就是把這個(gè)節(jié)點(diǎn)的更新給它完成了
  • unwindWork 是有節(jié)點(diǎn)的錯(cuò)誤,被捕獲,如何去處理的一個(gè)過(guò)程
  • 在上面的 SideEffect 到底有什么意義呢?
  • 比如有如下場(chǎng)景:
    • 有個(gè)列表上有值為 1, 2, 3的三個(gè)節(jié)點(diǎn)
    • 點(diǎn)擊 button 按鈕,會(huì)讓上面三個(gè)節(jié)點(diǎn)內(nèi)的值乘上自身
    • 對(duì)于2,3是4和9,對(duì)于1還是1
    • 這里 1 是一個(gè)沒(méi)有變化的過(guò)程
    • 按照正常邏輯來(lái)說(shuō),只需要更新原本值是 2 和 3 的節(jié)點(diǎn)
    • 實(shí)際上 react 里面也是這樣做的
  • 參考demo如下
    import React, { Component } from 'react'
    import './App.css'class List extends Component {state = {a: 1,b: 2,c: 3,}handleClick = () => {this.setState(oldState => {const { a, b, c } = oldStatereturn {a: a * a,b: b * b,c: c * c,}})}render() {const { a, b, c } = this.statereturn [<span key="a">{a}</span>,<span key="b">{b}</span>,<span key="c">{c}</span>,<button key="button" onClick={this.handleClick}>click me</button>,]}
    }class Input extends Component {state = {name: 'wang',}handleChange = e => {// 這里如果使用方法設(shè)置`state`// 那么需要現(xiàn)在外面讀取`e.target.value`// 因?yàn)樵赗eact走完整個(gè)事件之后會(huì)重置event對(duì)象// 以復(fù)用event對(duì)象,如果等到方法被調(diào)用的時(shí)候再讀取`e.target.value`// 那時(shí)`e.target`是`null`this.setState({name: e.target.value,})}render() {return (<inputtype="text"style={{ color: 'red' }}onChange={this.handleChange}value={this.state.name}/>)}
    }class App extends Component {render() {return (<div className="main"><Input /><List /></div>)}
    }export default App
    
  • 這個(gè)時(shí)候我們?cè)?瀏覽器中針對(duì) react-dom.development.js 在 commitRoot 上面打了一個(gè)斷點(diǎn)
  • 這個(gè)斷點(diǎn)是看最終要進(jìn)行commit的時(shí)候,它是如何去獲取哪幾個(gè)節(jié)點(diǎn)是要更新的
  • 也就是我們的 SideEffect 鏈?zhǔn)窃趺礃拥囊粋€(gè)形式, 點(diǎn)一下,斷點(diǎn)被捕獲,捕獲了之后
  • 可以看到它接收的兩個(gè)參數(shù),一個(gè)是root,一個(gè)是finishedWork,那么它們其實(shí)是一個(gè)對(duì)應(yīng)的關(guān)系
    • root.current.alternate 就等于 finishedWork
    • 因?yàn)?finishedWork 對(duì)應(yīng)的是 workInProgress
    • finishedWork 上面就會(huì)記錄我們當(dāng)前這一次更新,它所有需要去執(zhí)行的,就是要更新到dom上面的一些內(nèi)容
      • 它的記錄就在 firstEffect 到 lastEffect 的一個(gè)鏈上
      • 它這邊 firstEffect 記錄的 elementType 是一個(gè) span
      • 所謂 effect 它最終是一個(gè)fiber節(jié)點(diǎn),就是告訴我們哪一個(gè)fiber節(jié)點(diǎn)需要更新
      • 對(duì)于我們這邊第二個(gè)span,它的值是要被更新成4的
      • 所以可以看到它的 firstEffect 的第一個(gè)節(jié)點(diǎn)是 span
      • 它的 effectTag是 4,然后它的 updateQueen 的屬性里面是一個(gè)數(shù)組 updateQueue: ["children", "4"]
      • 這個(gè)大致意思可以看出,我們要把這個(gè)span標(biāo)簽對(duì)應(yīng)的dom節(jié)點(diǎn), 它的children里面顯示的文字內(nèi)容,從2變成4
      • 還有就是下一個(gè)節(jié)點(diǎn), 也是一個(gè)span, 看 nextEffect, 它的 elementType 也是span
      • 它的 updateQueen 是 updateQueue: ["children", "9"],也就是原值為 3 的節(jié)點(diǎn)
  • 對(duì)于commitWork,只會(huì)關(guān)心 firstEffect 到 lastEffect 這個(gè)鏈條上面的對(duì)應(yīng)的 fiber 節(jié)點(diǎn)
    • 它只需要更新的就是這兩個(gè)dom節(jié)點(diǎn)的children的一個(gè)變化
  • 這就是react里面的 vdom,它以最小化的程度去更新 dom
  • 而不需要對(duì)其他的任何節(jié)點(diǎn)再進(jìn)行一個(gè)操作,以此來(lái)提升一個(gè)性能
  • 這個(gè)過(guò)程, 就是在 v16.6.3/packages/react-reconciler/src/ReactFiberScheduler.js#L1026 這個(gè) if 里面被實(shí)現(xiàn)的
  • 這個(gè) demo 示例對(duì)應(yīng)最最上面的流程圖來(lái)說(shuō)
    • 這邊點(diǎn)了 button之后,在這里創(chuàng)建了一個(gè)update
    • 就是這個(gè)List上面, 通過(guò)調(diào)用 this.setState 去創(chuàng)建了這個(gè) update
    • 最終是要從 RootFiber 上面往下進(jìn)行一個(gè)更新,更新到 List 中的第一個(gè)span,以及后續(xù)的span
    • 然后發(fā)現(xiàn)只有第2和第3個(gè)span,它們的 children從 2 變成了 4,從 3 變成了 9
    • 它們兩個(gè)對(duì)應(yīng)的 SideEffect 是 Update 對(duì)應(yīng)值為4 (二進(jìn)制的表示形式, 參考 ReactSideEffectTags.js),它們要把內(nèi)容掛載到dom上面
    • 第一個(gè)span的內(nèi)容因?yàn)槭?乘以1,所以它沒(méi)有變化,就不需要執(zhí)行真正的更新
    • 首先執(zhí)行 completeUnitOfWork 的是 第一個(gè) span, 接下去它的 sibling
    • 因?yàn)榈谝粋€(gè) span 沒(méi)有 SideEffect,在這里,它的 returnFiber 就是 List
    • 當(dāng)前的 workInProgress 就是這第一個(gè) span,這個(gè)span沒(méi)有任何的 SideEffect
    • 這個(gè) List 自己也沒(méi)有 SideEffect,所以賦值List的時(shí)候,對(duì)List也是沒(méi)有任何的一個(gè)更新的, 如下
      if (returnFiber.firstEffect === null) {returnFiber.firstEffect = workInProgress.firstEffect;
      }
      
    • 這時(shí)候的 List 本身的 firstEffect 到 lastEffect是沒(méi)有任何內(nèi)容的,也就是null
    • 進(jìn)行到第2個(gè)span節(jié)點(diǎn),它自己有 SideEffect, 而它沒(méi)有子節(jié)點(diǎn)
    • 所以它本身上面的 firstEffect到lastEffect是沒(méi)有任何內(nèi)容的
    • 唯一需要操作的是要把它作為L(zhǎng)ist的第一個(gè) SideEffect 增加到這個(gè)鏈上面
    • 因?yàn)槭?Update, 值為 4 肯定是大于 Performedwork 值為 1的
      if (effectTag > PerformedWork) {if (returnFiber.lastEffect !== null) {returnFiber.lastEffect.nextEffect = workInProgress; // 情況1,標(biāo)記為 L1, 以便下面引用說(shuō)明} else {returnFiber.firstEffect = workInProgress; // 情況2, 標(biāo)記為 L2}returnFiber.lastEffect = workInProgress; // 通用設(shè)定3,標(biāo)記為 L3
      }
      
    • 它自身(workInProgress)要作為 returnFiber 的第一個(gè) SideEffect
    • 給它增加到 List 的firstEffect到lastEffect的鏈上
    • 所以returnFiber的 firstEffect 和 lastEffect,都等于這個(gè)Fiber對(duì)象(第二個(gè)span) workInProgress
    • 對(duì)應(yīng)的執(zhí)行語(yǔ)句是 L2L3
    • 當(dāng)?shù)?個(gè)span執(zhí)行complete完了,又要開(kāi)始它的sibling, 也就是第三個(gè)span
    • 第三個(gè)span也是有更新的,所以它也要增加到 List上面
    • 這個(gè)時(shí)候List上面已經(jīng)有變化,因?yàn)長(zhǎng)ist.lastEffect(姑且這樣表示)已經(jīng)不等于null了
    • 這個(gè)時(shí)候,執(zhí)行的是 else 的情況,即 L1
    • 因?yàn)樵谏弦粋€(gè)節(jié)點(diǎn)的complete過(guò)程當(dāng)中,已經(jīng)指定了 firstEffect 和 lastEffect 都為 workInProgress(第2個(gè)span)
    • 所以第二個(gè)span節(jié)點(diǎn)的 nextEffect 指向的是第三個(gè)span的節(jié)點(diǎn)
    • 它們更新完之后又要更新 button,因?yàn)樗鼪](méi)有任何的變化,所以 button 也沒(méi)有更新
    • 這個(gè)時(shí)候?qū)τ贚ist來(lái)說(shuō)它的 SideEffect 鏈?zhǔn)堑扔?span指向span的這么一個(gè)過(guò)程
    • List的firstEffect指向第二個(gè)span對(duì)應(yīng)的Fiber對(duì)象,lastEffect指向第三個(gè)span對(duì)應(yīng)的Fiber對(duì)象
    • List本身執(zhí)行 completeUnitOfWork 的時(shí)候,自己沒(méi)有任何的更新
    • 因?yàn)樗膕tate更新對(duì)于真正的dom操作,沒(méi)有任何的關(guān)系,而且它也沒(méi)有生命周期方法
    • 所以 List 后期沒(méi)有任何要做的事情了, 自己本身是沒(méi)有 SideEffect,只有子節(jié)點(diǎn)的 SideEffect
    • 在 List 執(zhí)行 completeUnitOfWork 的時(shí)候, 代碼中的 returnFiber 對(duì)應(yīng)是 div
    • 而 workInProgress 對(duì)應(yīng)的是 List, 而 List 要賦值它的 firstEffect 和 lastEffect
    • 它的鏈指向returnFiber, 就是要放到 returnFiber 它的鏈的最后面
    • returnFiber 這個(gè) div,它目前是肯定沒(méi)有任何的 SideEffect的, 所以它直接賦值成 workInProgress.firstEffect
    • 也就是說(shuō),對(duì)于 div 它的 firstEffect 跟 lastEffect 已經(jīng)變成 List 的 firstEffect 跟 lastEffect
    • 因?yàn)樯厦婀?jié)點(diǎn)都是沒(méi)有任何更新的, 所以一層一層往上之后, 在 RootFiber 上面記錄的
    • firstEffect 跟 lastEffect 也就變成了最開(kāi)始的兩個(gè)span
    • 所以這就是通過(guò) completeUnitOfWork,最終能夠賦值到 RootFiber 上面
    • 在它的 firstEffect 到 lastEffect,單項(xiàng)鏈表上面去記錄整個(gè)應(yīng)用當(dāng)中
    • 所有需要去更新的最終的dom節(jié)點(diǎn)以及組件的fiber對(duì)象的一個(gè)過(guò)程
    • 這里涉及到后期 commitRoot 的時(shí)候, 調(diào)用這個(gè)單項(xiàng)鏈表一個(gè)過(guò)程,這里先跳過(guò)
  • 對(duì)于 unwindWork 的一個(gè)過(guò)程, 也是相似的, 先跳過(guò) unwindWork 以及 completeWork
  • 目前只關(guān)心它的一個(gè)遍歷過(guò)程,跳過(guò)具體節(jié)點(diǎn)做的事情, 關(guān)注它的大致流程
  • 它真正幫我們?nèi)?shí)現(xiàn)了把所有需要更新的節(jié)點(diǎn)進(jìn)行一個(gè)串聯(lián)
  • 讓最終 commitRoot 的時(shí)候,能夠方便獲取到所有需要更新的節(jié)點(diǎn)的一個(gè)過(guò)程
http://m.risenshineclean.com/news/61690.html

相關(guān)文章:

  • 搬瓦工如何搭建做網(wǎng)站品牌營(yíng)銷(xiāo)包括哪些內(nèi)容
  • 凡科輕站小程序靠譜嗎一級(jí)域名二級(jí)域名三級(jí)域名的區(qū)別
  • 個(gè)人注冊(cè)域名可以做網(wǎng)站么新聞熱點(diǎn)事件2024最新
  • php 企業(yè)網(wǎng)站管理系統(tǒng)百度站長(zhǎng)平臺(tái)快速收錄
  • 制作網(wǎng)站建設(shè)寧德市委書(shū)記
  • 建設(shè)網(wǎng)站企業(yè)銀行關(guān)鍵詞全網(wǎng)搜索
  • 網(wǎng)站建設(shè)教程開(kāi)源代碼下載競(jìng)價(jià)托管 微競(jìng)價(jià)
  • 采購(gòu)管理系統(tǒng)免費(fèi)版seo企業(yè)優(yōu)化顧問(wèn)
  • 濟(jì)南營(yíng)銷(xiāo)型網(wǎng)站建設(shè)百度推廣400電話
  • 常州市建設(shè)工程質(zhì)監(jiān)站網(wǎng)站2022年十大流行語(yǔ)
  • 做網(wǎng)站運(yùn)營(yíng)需要具備哪些能力賣(mài)網(wǎng)站鏈接
  • 域名交易網(wǎng)站源代碼下載全球十大搜索引擎排名
  • 凡科網(wǎng)站怎么做鏈接精準(zhǔn)引流獲客軟件
  • 平面設(shè)計(jì)要素石首seo排名
  • 做市場(chǎng)調(diào)查的網(wǎng)站百度信息流廣告
  • 北京 網(wǎng)站建設(shè)公司長(zhǎng)沙seo行者seo09
  • 網(wǎng)站建設(shè)銷(xiāo)售技巧話術(shù)91永久免費(fèi)海外地域網(wǎng)名
  • 去年做那個(gè)網(wǎng)站致富免費(fèi)推廣引流軟件
  • 淘寶網(wǎng)站建設(shè)的主要工作怎么在百度做廣告
  • 濟(jì)南做網(wǎng)站的網(wǎng)絡(luò)公司西安seo服務(wù)公司排名
  • 網(wǎng)站建設(shè) 推廣 公司官網(wǎng)整站優(yōu)化
  • 怎么樣用ppt做網(wǎng)站百度最怕哪個(gè)部門(mén)去投訴
  • 市局政府網(wǎng)站建設(shè)管理情況匯報(bào)seo的作用主要有
  • 越秀網(wǎng)站建設(shè)設(shè)計(jì)自媒體是什么
  • 軟件公司網(wǎng)站建設(shè)安徽網(wǎng)站推廣公司
  • 群暉nas 做網(wǎng)站抖音視頻seo霸屏
  • 一流的成都 網(wǎng)站建設(shè)鄭州外語(yǔ)網(wǎng)站建站優(yōu)化
  • 坪地網(wǎng)站建設(shè)如何seo技術(shù)是什么意思
  • 成都個(gè)人兼職做網(wǎng)站行業(yè)關(guān)鍵詞搜索量排名
  • 成都智能建站模板平臺(tái)交易網(wǎng)