組件的生命週期可分成三個狀態:
- Mounting:已插入真實 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真實 DOM
生命週期的方法有:
componentWillMount
在渲染前調用,在客戶端也在服務端。一般用的比較少,更多的是用在服務端渲染
1、組件剛經歷constructor,初始完數據
2、組件還未進入render,組件還未渲染完成,dom還未渲染
componentDidMount
在第一次渲染後調用,只在客戶端。之後組件已經生成了對應的DOM結構,可以通過this.getDOMNode()來進行訪問。 如果你想和其他JavaScript框架一起使用,可以在這個方法中調用setTimeout, setInterval或者發送AJAX請求等操作(防止異步操作阻塞UI)。
組件第一次渲染完成,此時dom節點已經生成,可以在這裏調用ajax請求,返回數據setState後組件會重新渲染
componentWillReceiveProps
在組件接收到一個新的 prop (更新後)時被調用。這個方法在初始化render時不會被調用。
shouldComponentUpdate
返回一個布爾值。在組件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。
可以在你確認不需要更新組件時使用。
componentWillUpdate
在組件接收到新的props或者state但還沒有render時被調用。在初始化時不會被調用。
componentDidUpdate
在組件完成更新後立即調用。在初始化時不會被調用。
componentWillUnmount
在組件從 DOM 中移除之前立刻被調用。
class Demo extends Component {
constructor(props, context) {
//如果想(在組件其他地方是可以直接接收的)使用props或context,則需要以參數形式傳入。
//只要組件存在constructor,就必要要寫super,否則this指向會錯誤
super(props, context);
this.state = {
data: 1
};
},
componentWillMount () {
// 在組件掛載之前調用,且全局只調用一次。如果在這個鉤子裏可以setState,render後可以看到更新後的state,不會觸發重複渲染。
// 該生命週期可以發起異步請求,並setState。(React v16.3後廢棄該生命週期,可以在constructor中完成設置state)
// 不推薦在這裏發起ajax請求,若返回數據爲空,則容易造成界面空白,影響渲染效果
},
componentDidMount () {
//組件第一次渲染完成,此時dom節點已經生成,可以在這裏調用ajax請求,返回數據setState後組件會重新渲染
},
componentWillReceiveProps (nextProps) {
// 在接受父組件改變後的props需要重新渲染組件時用到的比較多
// 通過對比nextProps和this.props,將nextProps setState爲當前組件的state,從而重新渲染組件
nextProps.data !== this.props.data && this.setState({
data: nextProps.data
},() => {
console.log("new data...");
});
},
shouldComponentUpdate (nextProps, nextState) {
// react性能優化非常重要的一環。
// 組件接受新的state或者props時調用,我們可以設置在此對比前後兩個props和state是否相同,
// 如果相同則返回false阻止更新,因爲相同的屬性狀態一定會生成相同的dom樹,
// 這樣就不需要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤其是在dom結構複雜的時候。
},
componentWillUpdate (nextProps, nextState) {
// 組件初始化時不調用,只有在組件發生更新需要重新渲染時才調用
},
componentDidUpdate (prevProps, prevState) {
// 組件初始化時不調用,組件更新渲染完成後調用,此時dom節點加載完成,可以獲取到dom節點。
// react只會在第一次初始化成功會進入componentDidmount,
// 之後每次重新渲染後都會進入這個生命週期,這裏可以拿到prevProps和prevState,即更新前的props和state。
// 該鉤子內setState有可能會觸發重複渲染,需要謹慎判斷,否則會進入死循環
},
render () {
return (
<div>This is Demo!</div>
);
},
componentWillUnmount () {
// 組件將要卸載時調用,一些事件監聽和定時器需要在此時清除。
},
componentDidCatch (error, info) {
//React 16 中引入,用來 捕獲組件的錯誤。
//如果 render() 函數拋出錯誤,則會觸發該函數。
//錯誤在渲染階段中被捕獲,但在事件處理程序中不會被捕獲。
}
}
TIPS: 在生命週期中的哪一步你應該發起 AJAX 請求?
我們應當將AJAX 請求放到 componentDidMount 函數中執行,主要原因有下:
-
React 可能會多次頻繁調用 componentWillMount,如果我們將 AJAX 請求放到 componentWillMount 函數中,那麼顯而易見其會被觸發多次,自然也就不是好的選擇。
-
如果我們將 AJAX 請求放置在生命週期的其他函數中,我們並不能保證請求僅在組件掛載完畢後纔會要求響應。如果我們的數據請求在組件掛載之前就完成,並且調用了
setState
函數將數據添加到組件狀態中,對於未掛載的組件則會報錯。而在 componentDidMount 函數中進行 AJAX 請求則能有效避免這個問題。