React?Fiber?樹思想解決業(yè)務實際場景詳解
熟悉 Fiber 樹結構
我們知道,React 從 V16 版本開始采用 Fiber 樹架構來實現(xiàn)渲染和更新機制。
Fiber
在 React 源碼中可以看作是一個任務執(zhí)行單元,每個 React Element 都會有一個與之對應的 Fiber 節(jié)點。
Fiber
節(jié)點的核心數據結構如下:
type Fiber = { type: any, //類型 return: Fiber, //父節(jié)點 child: Fiber, // 指向第一個子節(jié)點 sibling: Fiber, // 指向下一個弟弟 }
其中,以下三個屬性可以構成 Fiber 樹:
return
表示父 Fiber 節(jié)點(頂級元素沒有 return 指針)sibling
表示下一個兄弟 Fiber 節(jié)點(如果沒有下一個兄弟節(jié)點,也就沒有這個指針)child
表示第一個子 Fiber 節(jié)點(如果沒有第一個子節(jié)點,也就沒有這個指針)。
舉個例子,假如我們的組件結構如下:
function App() { return ( <div> 名稱: <span>明里人</span> </div> ) }
對應的 Fiber 樹結構如下:
通過 Fiber 樹結構我們可以很方便的查找一個節(jié)點的上級、下級和同級。
接下來我們一起來看看實際的業(yè)務場景。
業(yè)務場景
有時我們會去實現(xiàn)一些任務類的需求,任務自身存在 status 狀態(tài),比如進行中、逾期、完成狀態(tài),每個任務都可以通過完成按鈕被完成。
假設現(xiàn)在有一個「任務流」作為第一級數據出現(xiàn),它的子集由一個或多個「任務組」組成,作為第二級數據出現(xiàn),任務組的子集由一個或多個「任務」組成,作為第三級數據出現(xiàn)。
現(xiàn)有需求如下:
第三級的「任務」在完成時更新自身狀態(tài),但要考慮同步上級節(jié)點的狀態(tài):
- 如果當前任務所在的任務組下所有任務都已完成,更新當前「任務組」狀態(tài)為完成;
- 如果所有任務組及任務都已完成,更新「任務流」狀態(tài)為完成。
當「任務流」處于完成狀態(tài)時,UI 的體現(xiàn)可能如下:
思路:
我們要在每個任務完成后,判斷同級任務是否都已完成,若都已完成,則將父級(任務組)狀態(tài)更新為完成。
如果我們將現(xiàn)有的菜單樹結構改造為 Fiber 樹結構,通過 return
可以很方便的找到父節(jié)點,然后通過 child 和 sibling
可以很方便的查找任務組下的每一個任務,決定是否更新任務組狀態(tài)。
代碼實現(xiàn)如下:
// 1. taskFlowData 任務流數據 // 2. currentTaskData 當前完成的任務數據 export const getFinishedStatus = (task) => task.status === 1; // 1 代表完成 export const setFinishedStatus = (task) => task.status = 1; // 首先,將當前任務的狀態(tài)更新 setFinishedStatus(currentTaskData); // 第一步,將現(xiàn)有數據轉換為 Fiber 樹結構 const createNode = (value, parent) => ( { value, return: parent, child: null, sibling: null } ); // 1-1. 創(chuàng)建 root fiber 根節(jié)點,即 任務流 const rootNode = createNode(taskFlowData, undefined); let currentNode = rootNode, currentTaskNode = null; // 1-2. child 存放的是任務組,為第二級數據創(chuàng)建 Fiber 節(jié)點 currentNode.value.child.forEach((taskGroup, taskGroupIndex) => { const node = createNode(taskGroup, rootNode); // 1-3. 建立關系 taskGroupIndex === 0 ? (currentNode.child = node) : (currentNode.sibling = node); // 1-4. 為第三級任務創(chuàng)建 Fiber 節(jié)點 taskGroup.child.forEach((task, taskIndex) => { const childNode = createNode(task, node); taskIndex === 0 ? (node.child = childNode) : (currentNode.sibling = childNode); currentNode = childNode; // 1-5. 記錄當前任務對應的 Fiber 節(jié)點 if (task.id === currentTaskData.id) currentTaskNode = currentNode; }); currentNode = node; }); // 第二步,根據 Fiber 樹結構,來查找并更新狀態(tài) let parentNode = currentTaskNode.return; while (parentNode) { let isFinished = true; // 2-1. 找到第一個任務 let workInprgress = parentNode.child; // 2-2. 從第一個任務開始,依次查看每個任務的狀態(tài) while (workInprgress) { // 2-3. 如果查找的當前任務處于未完成狀態(tài),無需更新父級狀態(tài) if (!getFinishedStatus(workInprgress.value)) { isFinished = false; break; } workInprgress = workInprgress.sibling; } // 2-4. 更新任務組狀態(tài),再向上查找,確定是否更新任務流狀態(tài) if (isFinished) { setFinishedStatus(parentNode.value); parentNode = parentNode.return; } else { // 2-5. 任務組狀態(tài)不需要更新,直接結束 break; } }
以上就是React Fiber 樹思想解決業(yè)務實際場景詳解的詳細內容,更多關于React Fiber樹業(yè)務場景的資料請關注腳本之家其它相關文章!
相關文章
React?中使用?react-i18next?國際化的過程(react-i18next?的基本用法)
i18next?是一款強大的國際化框架,react-i18next?是基于?i18next?適用于?React?的框架,本文介紹了?react-i18next?的基本用法,如果更特殊的需求,文章開頭的官方地址可以找到答案2023-01-01react-player實現(xiàn)視頻播放與自定義進度條效果
本篇文章通過完整的代碼給大家介紹了react-player實現(xiàn)視頻播放與自定義進度條效果,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2022-01-01ReactQuery系列React?Query?實踐示例詳解
這篇文章主要為大家介紹了ReactQuery系列React?Query?實踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11