React中父子組件生命周期的執(zhí)行順序
在 React 中,父子組件的生命周期執(zhí)行順序遵循一個清晰的規(guī)律:父組件先準備,子組件再掛載;子組件先卸載,父組件再清理。
核心原則:渲染階段由父到子(render 遞歸),提交階段(DOM 更新)再由子到父(componentDidMount/Update 遞歸)。
一、初始掛載階段(Mounting)
順序:父組件 getDerivedStateFromProps / render → 子組件生命周期 → 父組件 componentDidMount
詳細步驟(以類組件為例):
- 父組件:constructor
- 父組件:getDerivedStateFromProps
- 父組件:render
→ 此時解析出子組件實例,開始子組件的生命周期 - 子組件:constructor
- 子組件:getDerivedStateFromProps
- 子組件:render
- 子組件:componentDidMount
- 父組件:componentDidMount
注意:componentDidMount 是子組件先執(zhí)行,父組件后執(zhí)行。
二、更新階段(Updating)
觸發(fā)條件:props 或 state 改變。
2.1 由父組件 state 變化引起的更新
- 父組件:getDerivedStateFromProps
- 父組件:shouldComponentUpdate
- 父組件:render
→ 重新生成子組件,觸發(fā)子組件更新 - 子組件:getDerivedStateFromProps
- 子組件:shouldComponentUpdate
- 子組件:render
- 子組件:getSnapshotBeforeUpdate
- 子組件:componentDidUpdate
- 父組件:getSnapshotBeforeUpdate
- 父組件:componentDidUpdate
2.2 由子組件自身 state 變化引起的更新
只會觸發(fā)子組件自身的更新生命周期,父組件不受影響(除非子組件通過回調修改父組件 state)。
三、卸載階段(Unmounting)
順序:父組件先標記卸載 → 子組件 componentWillUnmount → 父組件 componentWillUnmount
- 父組件:決定卸載子組件(例如條件渲染移除子組件)
- 子組件:componentWillUnmount
- 父組件:componentWillUnmount
子組件先執(zhí)行清理工作,父組件最后清理。
四、函數(shù)組件中的近似順序(useEffect)
函數(shù)組件沒有直接等價的生命周期,但 useEffect 的執(zhí)行順序模擬了部分行為:
| 階段 | 類組件順序 | 函數(shù)組件近似順序 |
|---|---|---|
| 掛載 | 父 render → 子 render → 子 didMount → 父 didMount | 父 render → 子 render → 子 useLayoutEffect → 父 useLayoutEffect → 子 useEffect → 父 useEffect |
| 更新 | 父 render → 子 render → 子 didUpdate → 父 didUpdate | 類似,但 cleanup 在上一次 effect 之前執(zhí)行 |
| 卸載 | 子 willUnmount → 父 willUnmount | 子 useEffect cleanup → 父 useEffect cleanup |
注意:useEffect 是在瀏覽器完成布局與繪制之后異步執(zhí)行,所以 useEffect 中父子順序仍然是子先于父(因為組件樹是深度優(yōu)先渲染的)。
五、關鍵總結
- 掛載:父 render 先完成,但父 componentDidMount 要等所有子組件掛載完才執(zhí)行。
- 更新:父 render 先執(zhí)行,然后子組件更新,最后父 componentDidUpdate。
- 卸載:子組件先執(zhí)行 componentWillUnmount,父組件最后執(zhí)行。
- 函數(shù)組件:useEffect 的順序是子先于父,但執(zhí)行時間點在布局/繪制之后。
這個順序保證了:
- 子組件在父組件訪問它們之前已經準備好(或已清理)
- DOM 測量/滾動位置等操作可以在合適的時機進行
實例
以下是一個當前時間的實例,每秒更新:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, Runoob!</h1>
<h2>現(xiàn)在時間是:{this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
const root = ReactDOM.createRoot(document.body);
root.render(
<Clock />
);以下實例在 Hello 組件加載以后,通過 componentDidMount 方法設置一個定時器,每隔100毫秒重新設置組件的透明度,并重新渲染:
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {opacity: 1.0};
}
componentDidMount() {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
}
render () {
return (
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Hello name="world"/>
);以下實例初始化 state , setNewnumber 用于更新 state。所有生命周期在 Content 組件中。
class Button extends React.Component {
constructor(props) {
super(props);
this.state = { data: 0 };
this.setNewNumber = this.setNewNumber.bind(this);
}
setNewNumber() {
this.setState({ data: this.state.data + 1 });
}
render() {
return (
<div>
<button onClick={this.setNewNumber}>INCREMENT</button>
<Content myNumber={this.state.data} />
</div>
);
}
}
class Content extends React.Component {
componentDidMount() {
console.log("Component DID MOUNT!");
}
shouldComponentUpdate(newProps, newState) {
return true;
}
componentDidUpdate(prevProps, prevState) {
console.log("Component DID UPDATE!");
}
componentWillUnmount() {
console.log("Component WILL UNMOUNT!");
}
render() {
return (
<div>
<h3>{this.props.myNumber}</h3>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<div>
<Button />
</div>
);到此這篇關于React中父子組件生命周期的執(zhí)行順序的文章就介紹到這了,更多相關React 父子組件執(zhí)行順序內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
ReactNative?狀態(tài)管理redux使用詳解
這篇文章主要介紹了ReactNative?狀態(tài)管理redux使用詳解2023-03-03
React?高德地圖進京證路線規(guī)劃問題記錄(匯總)
這篇文章主要介紹了React高德地圖進京證路線規(guī)劃問題小記,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-08-08
詳解前端路由實現(xiàn)與react-router使用姿勢
本篇文章主要介紹了詳解前端路由和react-router使用姿勢,詳細的介紹了react-router的用法,有興趣的可以了解一下2017-08-08

