一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - React - 簡單分析React中的EffectList

簡單分析React中的EffectList

2022-02-24 16:47zhangyu React

這篇文章主要簡單分析了React中的EffectList,幫助大家更好的理解和學習使用React進行前端開發,感興趣的朋友可以了解下

React中,會遍歷EffectList來執行節點操作、生命周期方法、Effect方法,可以把EffectList比作圣誕樹上掛的彩燈,而這顆圣誕樹就是Fiber樹。

為什么會存在EffectList呢?打個比方來說,一顆Fiber樹中有一些Fiber節點需要執行componentDidMount方法,如果在Fiber樹構建完成后,再遍歷一次Fiber樹,找到需要執行componentDidMount方法的Fiber節點,這是非常低效的。

而EffectList就解決了這個問題,在Fiber樹構建過程中,每當一個Fiber節點的flags字段不為NoFlags時(代表需要執行副作用),就把該Fiber節點添加到EffectList,在Fiber樹構建完成后,由Fiber節點串成的彩燈也構建完成了,這樣僅僅需要遍歷彩燈就行了。

EffectList的收集

EffectList是一個單向鏈表,firstEffect代表鏈表中的第一個Fiber節點,lastEffect代表鏈表中的最后一個Fiber節點。

Fiber樹的構建是深度優先的,也就是先向下構建子級Fiber節點,子級節點構建完成后,再向上構建父級Fiber節點,所以EffectList中總是子級Fiber節點在前面。

Fiber節點構建完成的操作執行在completeUnitOfWork方法,在這個方法里,不僅會對節點完成構建,也會將有flags的Fiber節點添加到EffectList。

簡化代碼如下。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function completeUnitOfWork(unitOfWork: Fiber): void {
 let completedWork = unitOfWork;
 do {
  const current = completedWork.alternate;
  const returnFiber = completedWork.return;
  
  let next= completeWork(current, completedWork, subtreeRenderLanes);
 
  // effect list構建
  if (
   returnFiber !== null &&
   (returnFiber.flags & Incomplete) === NoFlags
  ) {
   // 層層拷貝
   if (returnFiber.firstEffect === null) {
    returnFiber.firstEffect = completedWork.firstEffect;
   }
   if (completedWork.lastEffect !== null) {
    // 說明當前節點是兄弟節點,子節點有effect,已經給returnFiber.lastEffect賦值過了
    if (returnFiber.lastEffect !== null) {
     // 連接兄弟節點的effect
     returnFiber.lastEffect.nextEffect = completedWork.firstEffect;
    }
    returnFiber.lastEffect = completedWork.lastEffect;
   }
   
   const flags = completedWork.flags;
   
   // 該fiber節點有effect
   if (flags > PerformedWork) {
    // 當前節點有effect連接上effect list
    if (returnFiber.lastEffect !== null) {
     returnFiber.lastEffect.nextEffect = completedWork;
    } else {
     // returnFiber沒有firstEffect的情況是第一次遇見有effect的節點
     returnFiber.firstEffect = completedWork;
    }
    returnFiber.lastEffect = completedWork;
   }
  }
 
  // 兄弟元素遍歷再到返返回父級
  const siblingFiber = completedWork.sibling;
  if (siblingFiber !== null) {
   workInProgress = siblingFiber;
   return;
  }
  completedWork = returnFiber;
  workInProgress = completedWork;
 } while (completedWork !== null);
}

EffectList實際是像冒泡一樣,一層一層不斷向上層收集,從第一個有flags的節點開始記錄,每層的新節點都會將上一個節點的firstEffectlastEffect拷貝到自身身上,再供上層節點再次拷貝。

如以下結構,假如每一個div都有flags。

?
1
2
3
4
5
6
<div id="1">
 <div id="4"/>
 <div id="2">
  <div id="3"/>
 </div>
</div>

最終形成的EffectList為

?
1
2
firstEffect => div4
lastEffect => div1

因為Fiber樹的構建深度優先,所有div4先完成completeWork,構建firstEffect。

EffectList遍歷是從firstEffect開始,通過每一個節點的nextEffect找到下一個節點。

?
1
2
3
4
firstEffect => div4
div4.nextEffect => div3
div3.nextEffect => div2
div2.nextEffect => div1

初次Render時的EffectList

在React中,會對初次Mount有一個性能優化,其中的Fiber節點的flags不會包含placement,對應的DOM節點不會遍歷加入DOM樹,而是在創建DOM節點時就已經加入DOM樹了,只有rootFiber節點FiberRootNodeflags會包含placement。

EffectList是不會包含root節點的,所以需要將root節點也添加到EffectList,這樣才會正確的執行placement,讓DOM樹在頁面呈現 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
let firstEffect;
// 把根節點finishedWork也連接進去
if (finishedWork.flags > PerformedWork) {
 if (finishedWork.lastEffect !== null) {
  finishedWork.lastEffect.nextEffect = finishedWork;
  firstEffect = finishedWork.firstEffect;
 } else {
  firstEffect = finishedWork;
 }
} else {
 // 根節點沒有effect.
 firstEffect = finishedWork.firstEffect;
}

EffectList的遍歷

EffectList的主要是用于Layout階段生命周期方法的執行和DOM的操作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 處理getSnapshotBeforeUpdate,調度useEffect
nextEffect = firstEffect;
do {
 commitBeforeMutationEffects();
} while (nextEffect !== null);
// DOM操作
nextEffect = firstEffect;
do {
 commitMutationEffects(root, renderPriorityLevel);
} while (nextEffect !== null);
// 生命周期方法的執行
nextEffect = firstEffect;
do {
 commitLayoutEffects(root, lanes);
} while (nextEffect !== null);

在這Layout階段的這3個方法里,會遍歷nextEffect,每執行完一個,就重新指向firstEffect。Layout階段具體操作就不細講了。

總結

EffectList不是全局變量,只是在Fiber樹創建過程中,一層層向上收集有effect的Fiber節點,最終的root節點就會收集到所有有effect到Fiber節點,我們就把這條包含effect節點的鏈表叫做EffectList。

由于收集的過程是深度優先,子級會先被收集,所以遍歷的時候也會先操作子級,所以如果有面試官問子級和父級的生命周期或者useEffect誰先執行,就很清楚的知道會先執行子級操作了。

以上就是簡單分析React中的EffectList的詳細內容,更多關于React中的EffectList的資料請關注服務器之家其它相關文章!

原文鏈接:https://juejin.cn/post/6947168516394975239

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 无人区乱码1区2区3区网站 | 奇米视频7777 | 30分钟的高清视频在线观看 | 韩国三级在线高速影院 | 国产永久在线观看 | 我与恶魔的h生活ova | 91免费精品国自产拍在线不卡 | 男人j桶进女人p桶爽 | 欧美久久久久久 | 四缺一小说| 水多多凹凸福利视频导航 | 青青青手机视频 | 亚洲日韩精品欧美一区二区一 | 色综合久久综精品 | 性欧美高清理论片 | 2019中文字幕 | 精品午夜视频 | 和日本免费不卡在线v | 色综合91久久精品中文字幕 | 双性少爷受糙汉攻h | 暴露狂婷婷医院暴露tx | 欧美日韩国产一区二区三区在线观看 | 男人的j进入女人的j免费 | 娇小性色 | 波多野结衣无码 | 狠狠干2017| 日本天堂网 | 2020年精品国产午夜福利在线 | 天堂bt在线 | 日本免费高清在线观看播放 | 青久久| 1024国产精品视频观看 | 亚洲男人天堂av | 国产东北3p真实在线456视频 | 国产免费好大好硬视频 | 日本xx高清视频免费观看 | a性片| 成人在线免费看 | 91免费播放人人爽人人快乐 | 国产亚洲女人久久久久久 | 精品国产91久久久久 |