react基礎(chǔ)知識(shí)總結(jié)
前言
最近在準(zhǔn)備面試。復(fù)習(xí)了一些react的知識(shí)點(diǎn),特此總結(jié)。
開始
React 生命周期
react 16以前的生命周期是這樣的
組件在首次渲染時(shí)會(huì)被實(shí)例化,然后調(diào)用實(shí)例上面的componentWillMount,render和componentDidMount函數(shù)。組件在更新渲染時(shí)可以調(diào)用componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render和componentDidUpdate函數(shù)。組件在卸載時(shí)可以調(diào)用componentWillUnmount函數(shù)。
借圖:
從 React v16.3 開始,React 建議使用getDerivedStateFromProps和getSnapshotBeforeUpdate兩個(gè)生命周期函數(shù)替代 componentWillMount,componentWillReceiveProps和componentWillUpdate三個(gè)生命周期函數(shù)。這里需要注意的是 新增的兩個(gè)生命周期 函數(shù)和原有的三個(gè)生命周期函數(shù)必須分開使用,不能混合使用
目前的生命周期(借圖):
componentWillMount存在的問題
有人認(rèn)為在componentWillMount中可以提前進(jìn)行異步請(qǐng)求,避免白屏。但是react在調(diào)用render渲染頁(yè)面的時(shí)候,render并不會(huì)等待異步請(qǐng)求結(jié)束,再獲取數(shù)據(jù)渲染。這么寫是有潛在隱患的。
而在react fiber之后 可能在一次渲染中多次調(diào)用。原因是:react fiber技術(shù)使用增量渲染來解決掉幀的問題,通過requestIdleCallback調(diào)度執(zhí)行每個(gè)任務(wù)單元,可以中斷和恢復(fù),生命周期一旦中斷,恢復(fù)之后會(huì)重新跑一次之前的生命周期
新的生命周期
static getDerivedStateFromProps
- 觸發(fā)時(shí)間(v16.4修正):組件每次被rerender的時(shí)候,包括在組件構(gòu)建之后(render之前最后執(zhí)行),每次獲取新的props或state之后。在v16.3版本時(shí),組件state的更新不會(huì)觸發(fā)該生命周期
- 每次接收新的props之后都會(huì)返回一個(gè)對(duì)象作為新的state,返回null則說明不需要更新state
- 配合componentDidUpdate,可以覆蓋componentWillReceiveProps的所有用法
getSnapshotBeforeUpdate
觸發(fā)時(shí)間: update發(fā)生的時(shí)候,在render之后,在組件dom渲染之前。
返回一個(gè)值,作為componentDidUpdate的第三個(gè)參數(shù)。
配合componentDidUpdate, 可以覆蓋componentWillUpdate的所有用法。
React Fiber
由于React渲染/更新過程一旦開始無法中斷,持續(xù)占用主線程,主線程忙于執(zhí)行JS,無暇他顧(布局、動(dòng)畫),造成掉幀、延遲響應(yīng)(甚至無響應(yīng))等不佳體驗(yàn)。fiber應(yīng)運(yùn)而生。
Fiber 是對(duì)react reconciler(調(diào)和) 核心算法的重構(gòu)。關(guān)鍵特性如下:
- 增量渲染(把渲染任務(wù)拆分成塊,勻到多幀)
- 更新時(shí)能夠暫停,終止,復(fù)用渲染任務(wù)
- 給不同類型的更新賦予優(yōu)先級(jí)
- 并發(fā)方面新的基礎(chǔ)能力
增量渲染用來解決掉幀的問題,渲染任務(wù)拆分之后,每次只做一小段,做完一段就把時(shí)間控制權(quán)交還給主線程,而不像之前長(zhǎng)時(shí)間占用。
Fiber tree
- Fiber之前的reconciler(被稱為Stack reconciler)自頂向下的遞歸mount/update,無法中斷(持續(xù)占用主線程),這樣主線程上的布局、動(dòng)畫等周期性任務(wù)以及交互響應(yīng)就無法立即得到處理,影響體驗(yàn)。
- Fiber解決這個(gè)問題的思路是把渲染/更新過程(遞歸diff)拆分成一系列小任務(wù),每次檢查樹上的一小部分,做完看是否還有時(shí)間繼續(xù)下一個(gè)任務(wù),有的話繼續(xù),沒有的話把自己掛起,主線程不忙的時(shí)候再繼續(xù)。
fiber樹其實(shí)是一個(gè)單鏈表結(jié)構(gòu),child指向第一個(gè)子節(jié)點(diǎn),return指向父節(jié)點(diǎn),sibling指向下個(gè)兄弟節(jié)點(diǎn)。結(jié)構(gòu)如下:
// fiber tree節(jié)點(diǎn)結(jié)構(gòu) { stateNode, child, return, sibling, ... }
Fiber reconciler
reconcile過程分為2個(gè)階段:
1.(可中斷)render/reconciliation 通過構(gòu)造workInProgress tree得出change
2.(不可中斷)commit 應(yīng)用這些DOM change(更新DOM樹、調(diào)用組件生命周期函數(shù)以及更新ref等內(nèi)部狀態(tài))
構(gòu)建workInProgress tree的過程就是diff的過程,通過requestIdleCallback來調(diào)度執(zhí)行一組任務(wù),每完成一個(gè)任務(wù)后回來看看有沒有插隊(duì)的(更緊急的),每完成一組任務(wù),把時(shí)間控制權(quán)交還給主線程,直到下一次requestIdleCallback回調(diào)再繼續(xù)構(gòu)建workInProgress tree
生命周期也被分成了兩個(gè)階段:
// 第1階段 render/reconciliation componentWillMount componentWillReceiveProps shouldComponentUpdate componentWillUpdate // 第2階段 commit componentDidMount componentDidUpdate componentWillUnmount
第1階段的生命周期函數(shù)可能會(huì)被多次調(diào)用,默認(rèn)以low優(yōu)先級(jí)執(zhí)行,被高優(yōu)先級(jí)任務(wù)打斷的話,稍后重新執(zhí)行。
fiber tree與workInProgress tree
雙緩沖技術(shù):指的是workInProgress tree構(gòu)造完畢,得到的就是新的fiber tree,然后把current指針指向workInProgress tree,由于fiber與workInProgress互相持有引用,舊fiber就作為新fiber更新的預(yù)留空間,達(dá)到復(fù)用fiber實(shí)例的目的。
每個(gè)fiber上都有個(gè)alternate屬性,也指向一個(gè)fiber,創(chuàng)建workInProgress節(jié)點(diǎn)時(shí)優(yōu)先取alternate,沒有的話就創(chuàng)建一個(gè)
let workInProgress = current.alternate; if (workInProgress === null) { //... workInProgress.alternate = current; current.alternate = workInProgress; } else { // We already have an alternate. // Reset the effect tag. workInProgress.effectTag = NoEffect; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; workInProgress.lastEffect = null; }
這么做的好處:
- 能夠復(fù)用內(nèi)部對(duì)象(fiber)
- 節(jié)省內(nèi)存分配、GC的時(shí)間開銷
fiber 中斷 恢復(fù)
中斷:檢查當(dāng)前正在處理的工作單元,保存當(dāng)前成果(firstEffect, lastEffect),修改tag標(biāo)記一下,迅速收尾并再開一個(gè)requestIdleCallback,下次有機(jī)會(huì)再做
斷點(diǎn)恢復(fù):下次再處理到該工作單元時(shí),看tag是被打斷的任務(wù),接著做未完成的部分或者重做
P.S.無論是時(shí)間用盡“自然”中斷,還是被高優(yōu)任務(wù)粗暴打斷,對(duì)中斷機(jī)制來說都一樣。
React setState
在代碼中調(diào)用setState函數(shù)之后,React 會(huì)將傳入的參數(shù)對(duì)象與組件當(dāng)前的狀態(tài)合并,然后觸發(fā)所謂的調(diào)和過程(Reconciliation)。經(jīng)過調(diào)和過程,React 會(huì)以相對(duì)高效的方式根據(jù)新的狀態(tài)構(gòu)建 React 元素樹并且著手重新渲染整個(gè)UI界面。在 React 得到元素樹之后,React 會(huì)自動(dòng)計(jì)算出新的樹與老樹的節(jié)點(diǎn)差異,然后根據(jù)差異對(duì)界面進(jìn)行最小化重渲染。在差異計(jì)算算法中,React 能夠相對(duì)精確地知道哪些位置發(fā)生了改變以及應(yīng)該如何改變,這就保證了按需更新,而不是全部重新渲染。
setState調(diào)用時(shí)有時(shí)是同步的(settimeout,自定義dom事件),有時(shí)是異步的(普通調(diào)用)
React 事件機(jī)制
React事件是通過事件代理,在最外層的 document上對(duì)事件進(jìn)行統(tǒng)一分發(fā),并沒有綁定在真實(shí)的 Dom節(jié)點(diǎn)上。 而且react內(nèi)部對(duì)原生的Event對(duì)象進(jìn)行了包裹處理。具有與瀏覽器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()。
以上就是react基礎(chǔ)知識(shí)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于react基礎(chǔ)知識(shí)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React報(bào)錯(cuò)Function?components?cannot?have?string?refs
這篇文章主要為大家介紹了React報(bào)錯(cuò)Function?components?cannot?have?string?refs解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12React報(bào)錯(cuò)map()?is?not?a?function詳析
這篇文章主要介紹了React報(bào)錯(cuò)map()?is?not?a?function詳析,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08React native ListView 增加頂部下拉刷新和底下點(diǎn)擊刷新示例
這篇文章主要介紹了React native ListView 增加頂部下拉刷新和底下點(diǎn)擊刷新示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04react如何同步獲取useState的最新狀態(tài)值
這篇文章主要介紹了react如何同步獲取useState的最新狀態(tài)值問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01React如何實(shí)現(xiàn)Vue的watch監(jiān)聽屬性
在 Vue 中可以簡(jiǎn)單地使用 watch 來監(jiān)聽數(shù)據(jù)的變化,還能獲取到改變前的舊值,而在 React 中是沒有 watch 的,今天通過本文給大家講解React實(shí)現(xiàn)Vue的watch監(jiān)聽屬性的方法,需要的朋友可以參考下2023-06-06react如何實(shí)現(xiàn)一個(gè)密碼強(qiáng)度檢測(cè)器詳解
這篇文章主要給大家介紹了關(guān)于react如何實(shí)現(xiàn)一個(gè)密碼強(qiáng)度檢測(cè)器的相關(guān)資料,使用這個(gè)密碼強(qiáng)度器后可以幫助大家提高在線帳號(hào)、個(gè)人信息的安全性,需要的朋友可以參考下2021-06-06