在本章節(jié)中我們將討論 React 組件的生命周期。
組件的生命周期可分成三個狀態(tài):
Mounting:已插入真實 DOM
Updating:正在被重新渲染
Unmounting:已移出真實 DOM
初始化階段:
getDefaultProps:獲取實例的默認屬性
getInitialState:獲取每個實例的初始化狀態(tài)
componentWillMount:組件即將被裝載、渲染到頁面上
render:組件在這里生成虛擬的 DOM 節(jié)點
componentDidMount:組件真正在被裝載之后
運行中狀態(tài):
componentWillReceiveProps:組件將要接收到屬性的時候調(diào)用
shouldComponentUpdate:組件接受到新屬性或者新狀態(tài)的時候(可以返回 false,接收數(shù)據(jù)后不更新,阻止 render 調(diào)用,后面的函數(shù)不會被繼續(xù)執(zhí)行了)
componentWillUpdate:組件即將更新不能修改屬性和狀態(tài)
render:組件重新描繪
componentDidUpdate:組件已經(jīng)更新
銷毀階段:
componentWillUnmount:組件即將銷毀
在未來 v17.0 版本中即將被移除的三個生命周期函數(shù) componentWillMount `,componentWillReceiveProps ,componentWillUpdate (現(xiàn)在這三個鉤子函數(shù)依然可以使用).
新增兩個鉤子函數(shù):
1. getDerivedStateFromProps(nextProps, prevState):
組件初始(重新渲染)加載時,獲取當前的props與state的值(在此鉤子函數(shù)中不能使用this),再此比較返回最新值對象(這個返回簡單點說就相當于setState),注意添加 條件不滿足時 return null;
官方例子:
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.translateX !== prevState.translateX) {
return {
translateX: nextProps.translateX,
};
}
return null;
}
2. getSnapshotBeforeUpdate(prevProps, prevState):
getSnapshotBeforeUpdate 會在最終的 render 之前被調(diào)用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態(tài)是可以保證與 componentDidUpdate 中一致的。雖然 getSnapshotBeforeUpdate 不是一個靜態(tài)方法,但我們也應(yīng)該盡量使用它去返回一個值。這個值會隨后被傳入到 componentDidUpdate 中,然后我們就可以在 componentDidUpdate 中去更新組件的狀態(tài),而不是在 getSnapshotBeforeUpdate 中直接更新組件狀態(tài)。
官方例子:
class ScrollingList extends React.Component {
listRef = null;
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
return (
this.listRef.scrollHeight - this.listRef.scrollTop
);
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
this.listRef.scrollTop =
this.listRef.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.setListRef}>
{/* ...contents... */}
</div>
);
}
setListRef = ref => {
this.listRef = ref;
};
}