激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品久久久久一区二区 | 天堂成人国产精品一区 | 91精品国产99久久久久久红楼 | 午夜生活理论片 | 亚洲成人中文字幕在线 | 久久99国产精品二区护士 | 欧美一区二区三区久久综合 | 九九精品影院 | 日韩午夜一区二区三区 | 天天透天天狠天天爱综合97 | 欧美一级片免费在线观看 | 黄色网欧美 | www.99re14.com | 国产免费一区二区三区在线能观看 | 亚洲视色 | 免费国产视频在线观看 | 成人一级在线 | 99欧美精品 | 情侣啪啪网站 | 日本在线视频二区 | 精品一区二区三区在线视频 | 成人店女老板视频在线看 | 性欧美视频在线观看 | 欧美毛片免费观看 | 黄色毛片前黄 | 性猛交ⅹxxx乱巴西 在线播放中文 | 国内自拍网址 | 99精品国产成人一区二区 | 成年人激情在线 | 亚洲生活片 | 欧美成人精品一区二区 | 在线91视频| 欧美日韩精品不卡一区二区三区 | 九九热在线精品视频 | av在线免费观看国产 | 亚洲精品永久视频 | 亚洲欧美一区二区三区在线观看 | 天天鲁在线视频免费观看 | 黄色av网站免费看 | 中文字幕一区2区 | 黄色网页在线观看 |