React中父子组件生命周期的执行顺序

 更新时间:2026年06月10日 09:08:50   作者:卷帘依旧  
在React中,父子组件的生命周期执行顺序遵循一个清晰的规律,父组件先准备,子组件再挂载;子组件先卸载,父组件再清理, 下面就来详细的介绍一下

在 React 中,父子组件的生命周期执行顺序遵循一个清晰的规律:父组件先准备,子组件再挂载;子组件先卸载,父组件再清理。

核心原则:渲染阶段由父到子(render 递归),提交阶段(DOM 更新)再由子到父(componentDidMount/Update 递归)。

一、初始挂载阶段(Mounting)

顺序:父组件 getDerivedStateFromProps / render → 子组件生命周期 → 父组件 componentDidMount

详细步骤(以类组件为例):

  1. 父组件:constructor
  2. 父组件:getDerivedStateFromProps
  3. 父组件:render
    → 此时解析出子组件实例,开始子组件的生命周期
  4. 子组件:constructor
  5. 子组件:getDerivedStateFromProps
  6. 子组件:render
  7. 子组件:componentDidMount
  8. 父组件:componentDidMount

注意:componentDidMount 是子组件先执行,父组件后执行。

二、更新阶段(Updating)

触发条件:props 或 state 改变。

2.1 由父组件 state 变化引起的更新

  1. 父组件:getDerivedStateFromProps
  2. 父组件:shouldComponentUpdate
  3. 父组件:render
    → 重新生成子组件,触发子组件更新
  4. 子组件:getDerivedStateFromProps
  5. 子组件:shouldComponentUpdate
  6. 子组件:render
  7. 子组件:getSnapshotBeforeUpdate
  8. 子组件:componentDidUpdate
  9. 父组件:getSnapshotBeforeUpdate
  10. 父组件:componentDidUpdate

2.2 由子组件自身 state 变化引起的更新

只会触发子组件自身的更新生命周期,父组件不受影响(除非子组件通过回调修改父组件 state)。

三、卸载阶段(Unmounting)

顺序:父组件先标记卸载 → 子组件 componentWillUnmount → 父组件 componentWillUnmount

  1. 父组件:决定卸载子组件(例如条件渲染移除子组件)
  2. 子组件:componentWillUnmount
  3. 父组件:componentWillUnmount

子组件先执行清理工作,父组件最后清理。

四、函数组件中的近似顺序(useEffect)

函数组件没有直接等价的生命周期,但 useEffect 的执行顺序模拟了部分行为:

阶段类组件顺序函数组件近似顺序
挂载父 render → 子 render → 子 didMount → 父 didMount父 render → 子 render → 子 useLayoutEffect → 父 useLayoutEffect → 子 useEffect → 父 useEffect
更新父 render → 子 render → 子 didUpdate → 父 didUpdate类似,但 cleanup 在上一次 effect 之前执行
卸载子 willUnmount → 父 willUnmount子 useEffect cleanup → 父 useEffect cleanup

注意:useEffect 是在浏览器完成布局与绘制之后异步执行,所以 useEffect 中父子顺序仍然是子先于父(因为组件树是深度优先渲染的)。

五、关键总结

  • 挂载:父 render 先完成,但父 componentDidMount 要等所有子组件挂载完才执行。
  • 更新:父 render 先执行,然后子组件更新,最后父 componentDidUpdate。
  • 卸载:子组件先执行 componentWillUnmount,父组件最后执行。
  • 函数组件:useEffect 的顺序是子先于父,但执行时间点在布局/绘制之后。

这个顺序保证了:

  • 子组件在父组件访问它们之前已经准备好(或已清理)
  • 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>现在时间是:{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中父子组件生命周期的执行顺序的文章就介绍到这了,更多相关React 父子组件执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • react中定义变量并使用方式

    react中定义变量并使用方式

    这篇文章主要介绍了react中定义变量并使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • ReactNative 状态管理redux使用详解

    ReactNative 状态管理redux使用详解

    这篇文章主要介绍了ReactNative 状态管理redux使用详解
    2023-03-03
  • React组件与事件的创建使用教程

    React组件与事件的创建使用教程

    react事件绑定时。this并不会指向当前DOM元素。往往使用bind来改变this指向,今天通过本文给大家介绍React事件绑定的方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-02-02
  • React 高德地图进京证路线规划问题记录(汇总)

    React 高德地图进京证路线规划问题记录(汇总)

    这篇文章主要介绍了React高德地图进京证路线规划问题小记,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • react项目自行配置热更新的实现

    react项目自行配置热更新的实现

    本文主要介绍了react项目自行配置热更新的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-11-11
  • 详解前端路由实现与react-router使用姿势

    详解前端路由实现与react-router使用姿势

    本篇文章主要介绍了详解前端路由和react-router使用姿势,详细的介绍了react-router的用法,有兴趣的可以了解一下
    2017-08-08
  • React优化子组件render的使用

    React优化子组件render的使用

    这篇文章主要介绍了React优化子组件render的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • Rust中Trait的使用

    Rust中Trait的使用

    在Rust中,Trait是一个核心概念,它允许我们定义类型应该具有的行为,本文就来具体介绍一下Rust中Trait的使用,感兴趣的可以了解一下,感兴趣可以了解一下
    2024-03-03
  • 使用react和redux构建一个简单的计数器

    使用react和redux构建一个简单的计数器

    这篇文章主要为大家详细介绍了如何使用react和redux构建一个简单的计数器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-01-01
  • React Native实现地址挑选器功能

    React Native实现地址挑选器功能

    这篇文章主要为大家详细介绍了React Native仿地址挑选器功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10

最新评论