中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

useEffect返回函數執行過程是什么

發布時間:2023-04-17 10:46:02 來源:億速云 閱讀:136 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“useEffect返回函數執行過程是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“useEffect返回函數執行過程是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

下面是源碼簡化:

function recursivelyTraversePassiveUnmountEffects(parentFiber: Fiber): void {
  const deletions = parentFiber.deletions;
  if ((parentFiber.flags & ChildDeletion) !== NoFlags) {
    if (deletions !== null) {
      for (let i = 0; i < deletions.length; i++) {
        const childToDelete = deletions[i];
        nextEffect = childToDelete;
        commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
          childToDelete,
          parentFiber
        );
      }
    }
  }
}
function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
  deletedSubtreeRoot: Fiber,
  nearestMountedAncestor: Fiber | null
) {
  while (nextEffect !== null) {
    const fiber = nextEffect;
    // 執行 passive effects 返回的函數
    commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);

    const child = fiber.child;
    if (child !== null) {
      child.return = fiber;
      nextEffect = child;
    } else {
      commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
        deletedSubtreeRoot
      );
    }
  }
}

function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
  deletedSubtreeRoot
) {
  while (nextEffect !== null) {
    const fiber = nextEffect;
    const sibling = fiber.sibling;
    const returnFiber = fiber.return;

    if (fiber === deletedSubtreeRoot) {
      nextEffect = null;
      return;
    }

    if (sibling !== null) {
      sibling.return = returnFiber;
      nextEffect = sibling;
      return;
    }

    nextEffect = returnFiber;
  }
}

deletions

在正式開始之前,我們要了解一個 fiber 的屬性:deletions

這個屬性存放的是當前節點中被刪除的 fiber,這個數組是在 commit 階段被賦值的

如果有被刪除的節點,這個屬性值是一個數組,如果沒有被刪除的節點,這個屬性值是 null

const A = () => {
  useEffect(() => {
    return () => {
      console.log("A unmount");
    };
  }, []);
  return <div>文本A</div>;
};
const B = () => {
  useEffect(() => {
    return () => {
      console.log("B unmount");
    };
  }, []);
  return <div>文本B</div>;
};

如果 App 組件這樣寫,那么 deletions 的值是 [FiberNode, FiberNode]

const App(){
  const [count, setCount] = useState(0)

  return <div>
    {count % 2 === 0 && <A />}
    {count % 2 === 0 && <B />}
    <div onClick={()=> setCount(count+1)}>+1</div>
  </div>
}

如果 App 組件這樣寫,那么 deletions 的值是 [FiberNode]

const App(){
  const [count, setCount] = useState(0)

  return <div>
    {count % 2 === 0 && <><A /><B /></>}
    <div onClick={()=> setCount(count+1)}>+1</div>
  </div>
}

對于第二種情況,react 會把 A 組件和 B 組件作為一個整體,所以 deletions 的值是 [FiberNode]

處理當前節點的 deletions

react 在遍歷 fiber tree 時,會先處理當前的 fiberdeletions,等處理完之后再遍歷下一個 fiber

現在我們已經知道 deletions 中保存的是當前 fiber 下被刪除的子節點

這時 react 會遍歷 deletions 數組,然后執行每個 fiberpassive effect 返回的函數

但是有個問題,如果 deletions 中的 fiber 有子節點,那么這些子節點也會被刪除,這時 react 會怎么處理呢?

這里分兩種情況來討論:

  • 刪除的 fiber 沒有子節點:<div>{xxxx && <A />}</div>

  • 刪除的 fiber 有子節點:<div>{xxxx && <><A /><B /></>}</div> -->

刪除的 fiber 沒有子節點:<div>{xxxx && <A />}</div>

這種情況比較好理解

當遍歷到 div 時,因為 <A/> 節點會被卸載,所以在 divdeletions 保存了一個 <A/>fiber

遍歷 deletions 數組,執行 <A/>passive effect 返回的函數

如下圖所示:

useEffect返回函數執行過程是什么

刪除的 fiber 有子節點:<div>{xxxx && <><A /><B /></>}</div>

這種情況就比較復雜了

當遍歷到 div 時,<></> 節點會被卸載,所以在 divdeletions 保存了一個 <></>fiber

遍歷 deletions 數組,執行 fiberpassive effect 返回的函數,對于 <></> 來說是不存在的 passive effect

那么這個時候就要去遍歷它的 child.fiber,也就是 <A/><B/>

首先拿到第一個 fiber,也就是 <A/>,然后執行 <A/>passive effect 返回的函數,這步比較好理解

child = fiber.child;
if (child !== null) {
  nextEffect = child;
}

這里遍歷也是深度優先,遍歷一個 child,執行一個 passive effect 返回函數,然后再遍歷下一個 child(這邊 <A /> 已經是葉子節點了)

然后拿到第二個 fiber,也就是 <B/>,然后執行 <B/>passive effect 返回的函數,這步就不太好理解了

child = fiber.child;
if (child !== null) {
  nextEffect = child;
} else {
  commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot);
}

這里要注意的是:

react 在尋找有 passive effectfiber 時,只遍歷到有 passive effectfiber, 像 div 這種沒有 passive effect 就不會遍歷

但是在處理 deletionsreact 會遍歷所有的 fiber,也就是說從當前的 fiber 開始,一直往下遍歷到葉子節點,這個葉子節點是指文本節點這種,往下不會有節點了(對于 A 組件來說 文本A 是文本節點)

然后在開始往上遍歷,往上遍歷是調用 commitPassiveUnmountEffectsInsideOfDeletedTree_complete 函數,直到遍歷到 deletionRoot,在向上遍歷的過程中會檢查是否有 sibling,如果有說明 sibling 還沒被處理,這樣就找到了 <B/>,然后執行 <B/>passive effect 返回的函數

如下圖所示:

useEffect返回函數執行過程是什么

向下遍歷和向上遍歷

在處理 deletions 時,對于每個 deletedNode,都先向下遍歷,然后再向上遍歷

  • 向下遍歷:commitPassiveUnmountEffectsInsideOfDeletedTree_begin(深度優先,優先處理左邊的節點)

  • 向上遍歷:commitPassiveUnmountEffectsInsideOfDeletedTree_complete(之后再處理右邊節點)

總結

1. 遍歷 deletions 數組:

  • react 在處理 deletions 時,先沿著 fiber tree 向下遍歷,如果有 passive effect 返回的函數,則執行

  • 一直遍歷到沒有 childfiber,再向上遍歷,處理 sibling

  • 再向上遍歷時,如果如果遇到 sibling,再向下遍歷,向下遍歷時遇到 passive effect 返回的函數,則執行

  • 如此循環直到遍歷到 deletedNode,結束遍歷

2. 結合掌握 React 組件樹遍歷技巧

  • 遍歷尋找有 passive effect 節點

    • react 從根組件向下遍歷,如果沒有 passive effect,則不會遍歷

  • 遍歷時,如果遇到當前節點有 deletions 時,會暫停尋找 passive effect 節點

    • 進入遍歷 deletions 數組

react 遍歷 deletions 完整邏輯如下圖所示:

圖中綠色部分是遍歷 deletionsNode 過程,紅色部分是遍歷尋找 passive effect 過程

useEffect返回函數執行過程是什么

讀到這里,這篇“useEffect返回函數執行過程是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

邹平县| 盘锦市| 乌兰浩特市| 昌宁县| 申扎县| 丰宁| 南阳市| 富裕县| 泾川县| 福建省| 临洮县| 固安县| 界首市| 彝良县| 青川县| 丰镇市| 西乌珠穆沁旗| 静乐县| 来宾市| 翁源县| 乳山市| 嵊州市| 隆化县| 微博| 河北省| 咸阳市| 齐齐哈尔市| 新泰市| 阳信县| 香河县| 九龙坡区| 南丰县| 中宁县| 平利县| 建平县| 县级市| 黄冈市| 白朗县| 高碑店市| 通化市| 鄄城县|