React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > React 父子组件执行顺序

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

作者:卷帘依旧

在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 中父子顺序仍然是子先于父(因为组件树是深度优先渲染的)。

五、关键总结

这个顺序保证了:

实例

以下是一个当前时间的实例,每秒更新:

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 父子组件执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文