React.js
[TOC]
生命周期
所謂的生命周期就是指某個事物從開始到結(jié)束的各個階段,當然在 <u>React.js</u> 中指的是組件從創(chuàng)建到銷毀的過程经磅,<u>React.js</u> 在這個過程中的不同階段調(diào)用的函數(shù)枕荞,通過這些函數(shù)歉井,我們可以更加精確的對組件進行控制甚疟,前面我們一直在使用的 <u>render</u> 函數(shù)其實就是組件生命周期渲染階段執(zhí)行的函數(shù)
周期分類
<u>React.js</u> 為組件的生命周期劃分了四個
不同的階段
- 掛載階段
- 更新階段
- 卸載階段
- 錯誤處理
wd不同的階段又會對應著一些不同的函數(shù)
參考:http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
[圖片上傳失敗...(image-5cb90e-1614087199201)]
掛載階段
掛載階段是指組件創(chuàng)建到渲染到頁面的過程茧跋,這個過程提供了四個
不同的函數(shù)
- constructor()
- render()
- static getDerivedStateFromProps()
- componentDidMount()
constructor
constructor(props)
類的構(gòu)造函數(shù)颤芬,也是組件初始化函數(shù)悲幅,一般情況下孽文,我們會在這個階段做一些初始化的工作
- 初始化 <u>state</u>
- 處理事件綁定函數(shù)的 <u>this</u>
render()
<u>render</u> 方法是 <u>Class</u> 組件必須實現(xiàn)的方法
static getDerivedStateFromProps()
static getDerivedStateFromProps(props, state)
該方法會在 <u>render</u> 方法之前調(diào)用,無論是掛載階段還是更新階段夺艰,它的存在只有一個目的:讓組件在 <u>props</u> 變化時更新 <u>state</u>
componentDidMount()
componentDidMount()
在組件掛載后(<u>render</u> 的內(nèi)容插入 <u>DOM</u> 樹中)調(diào)用芋哭。通常在這個階段,我們可以:
- 操作 <u>DOM</u> 節(jié)點
- 發(fā)送請求
更新階段
更新階段是指組件重新渲染的過程郁副,組件 <u>state</u> 的更新(調(diào)用 <u>setState()</u>)和父組件渲染都會觸發(fā)
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
static getDerivedStateFromProps()
同掛載階段减牺,更新階段也會觸發(fā)該生命周期函數(shù)
shouldComponentUpdate()
shouldComponentUpdate(nextProps, nextState)
發(fā)生在更新階段,<u>getDerivedStateFromProps</u> 之后存谎,<u>render</u> 之前拔疚,該函數(shù)會返回一個布爾值,決定了后續(xù)是否執(zhí)行 <u>render</u>既荚,首次渲染不會調(diào)用該函數(shù)
import React from 'react';
import Child from './Child';
export default class ShouldComponentUpdateComponent extends React.Component {
constructor(...args) {
super(...args);
this.state = {
n: 1,
}
}
render() {
return(
<div>
<h2 onClick={e=> {
this.setState({n: this.state.n + 1})
}}>n: {this.state.n}</h2>
<Child value={this.state.n} />
</div>
)
}
}
import React from 'react';
export default class Child extends React.Component {
constructor(...props) {
super(...props);
this.state = {
value: this.props.value
};
}
shouldComponentUpdate(nextProps, nextState) {
return this.state.value !== nextState.value;
}
render() {
console.log('render');
return(
<div>
value: {this.state.value}
<button onClick={e=>{
this.setState({
value: this.state.value + 1
})
}}>+</button>
</div>
);
}
}
此方法僅作為性能優(yōu)化的方式而存在稚失,不要企圖依靠此方法來“阻止”渲染,因為可能會產(chǎn)生一些問題恰聘。其次句各,在 <u>React.js</u> 中本來對渲染已經(jīng)做了必要的優(yōu)化了,所以通過該函數(shù)本質(zhì)上不能帶來特別大的明顯提升晴叨,且容易增加組件的復雜性凿宾,變得難以維護,除非確定使用它能為當前組件帶來顯著的性能提升
官方后期也會更改該方法的特性兼蕊,即使返回 <u>false</u> 仍可能會重新渲染組件
不推薦濫用該函數(shù)
render()
同上
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate(prevProps, prevState)
該方法在 <u>render()</u> 之后初厚,但是在輸出到 <u>DOM</u> 之前執(zhí)行,用來獲取渲染之前的快照孙技。當我們想在當前一次更新前獲取上次的 <u>DOM</u> 狀態(tài)产禾,可以在這里進行處理,該函數(shù)的返回值將作為參數(shù)傳遞給下個生命周期函數(shù) <u>componentDidUpdate</u>
該函數(shù)并不常用牵啦。
componentDidUpdate()
componentDidUpdate(prevProps, prevState, snapshot)
該函數(shù)會在 <u>DOM</u> 更新后立即調(diào)用亚情,首次渲染不會調(diào)用該方法。我們可以在這個函數(shù)中對渲染后的 <u>DOM</u> 進行操作
卸載階段
當組件從 DOM 中移除時會調(diào)用如下方法
- componentWillUnmount()
componentWillUnmount()
componentWillUnmount()
該方法會在組件卸載及銷毀前調(diào)用蕾久,我們可以在這里做一些清理工作势似,如:組件內(nèi)的定時器、未完成的請求等
錯誤處理
當渲染過程僧著,子組件的構(gòu)造函數(shù)或生命周期中拋出錯誤時履因,會調(diào)用如下方法
- static getDerivedStateFromError()
- componentDidCatch()
static getDerivedStateFromError()
static getDerivedStateFromError(error)
該方法用來獲取子組件拋出的錯誤,返回值是一個對象盹愚,該對象被存儲在 <u>state</u> 中栅迄,在后續(xù)的 <u>render</u> 方法中就可以根據(jù)這個對象的值來進行處理,如:顯示不同的 <u>UI</u>
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <div>出錯了</div>;
}
return this.props.children;
}
}
componentDidCatch()
componentDidCatch(error, info)
該方法與 <u>getDerivedStateFromError()</u> 類似皆怕,但是也有不同的地方:
- 該方法會有一個記錄詳細錯誤堆棧信息的 <u>info</u> 參數(shù)
- 該方法可以執(zhí)行一些額外的操作:打印錯誤毅舆、上報錯誤信息……