React 生命周期

组件的生命周期

React 中的每个组件都有一个生命周期,您可以在其三个主要阶段对其进行监控和操作。

三个阶段是:安装更新卸载


安装

安装意味着将元素放入 DOM。

React 有四个内置方法,在安装组件时按此顺序调用:

  1. constructor()
  2. getDerivedStateFromProps()
  3. render()
  4. componentDidMount()

render() 方法是必需的并且总是被调用,其他是可选的,如果你定义了它们就会被调用。


constructor

constructor() 方法在其他任何事情之前被调用,当组件启动时,它是设置初始 state 和其他初始值。

constructor() 方法以 props 作为参数调用,您应该始终先调用 super(props),然后再调用其他任何方法,这将启动父级的构造方法并允许组件从其父级 (React.Component) 继承方法。

示例:

constructor 方法被 React 调用,每次你创建一个组件时:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

getDerivedStateFromProps

getDerivedStateFromProps() 方法在渲染 DOM 中的元素之前调用。

这是根据初始 props 设置 state 对象的自然位置。

它以 state 作为参数,并返回一个对 state 进行更改的对象。

下面的示例以最喜欢的颜色为 "red" 开始,但 getDerivedStateFromProps() 方法根据 favcol 属性更新最喜欢的颜色:

示例:

getDerivedStateFromProps 方法在 render 方法之前被调用:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  static getDerivedStateFromProps(props, state) {
    return {favoritecolor: props.favcol };
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));

render

render() 方法是必需的,并且是实际将 HTML 输出到 DOM 的方法。

示例:

一个带有简单 render() 方法的简单组件:

class Header extends React.Component {
  render() {
    return (
      <h1>This is the content of the Header component</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

componentDidMount

componentDidMount() 方法在组件渲染后调用。

这是您运行要求组件已放置在 DOM 中的语句的地方。

示例:

起初我最喜欢的颜色是红色,但等一下,它变成了黄色:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

Updating

生命周期的下一个阶段是组件更新

只要组件的 stateprops 发生变化,就会更新组件。

React 有五个内置方法,当组件更新时,它们会按此顺序被调用:

  1. getDerivedStateFromProps()
  2. shouldComponentUpdate()
  3. render()
  4. getSnapshotBeforeUpdate()
  5. componentDidUpdate()

render() 方法是必需的并且总是会被调用,其他是可选的,如果你定义了它们就会被调用。


getDerivedStateFromProps

同样在 updates 处调用 getDerivedStateFromProps 方法。 这是组件更新时调用的第一个方法。

这仍然是根据初始 props 设置 state 对象的自然位置。

下面的示例有一个按钮,可以将喜欢的颜色更改为蓝色,但是由于调用了 getDerivedStateFromProps() 方法,该方法使用来自 favcol 属性的颜色更新状态, 最喜欢的颜色仍然呈现为黄色:

示例:

如果组件得到更新,则调用 getDerivedStateFromProps() 方法:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  static getDerivedStateFromProps(props, state) {
    return {favoritecolor: props.favcol };
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));

shouldComponentUpdate

shouldComponentUpdate() 方法中,您可以返回一个布尔值,指定 React 是否应该继续渲染。

默认值为 true

下面的示例显示了当 shouldComponentUpdate() 方法返回 false 时会发生什么:

示例:

在任何更新时停止渲染组件:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  shouldComponentUpdate() {
    return false;
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

示例:

与上面的示例相同,但这次 shouldComponentUpdate() 方法返回 true:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  shouldComponentUpdate() {
    return true;
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

render

render() 方法当然会在组件更新时调用,它必须将 HTML 重新渲染到 DOM,使用 新的变化。

下面的示例有一个按钮,可以将喜欢的颜色更改为蓝色:

示例:

单击按钮以更改组件的状态:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate() 方法中,您可以访问 propsstate 之前的更新,这意味着即使在更新之后,您也可以检查更新之前 之前 的值。

如果存在 getSnapshotBeforeUpdate() 方法,还应该包含 componentDidUpdate() 方法,否则会报错。

下面的示例可能看起来很复杂,但它所做的只是:

当组件 安装 时,它会以最喜欢的颜色 "red" 呈现。

当组件已安装时,计时器会更改状态,一秒钟后,最喜欢的颜色变为 "yellow"。

这个动作触发了更新阶段,由于这个组件有一个 getSnapshotBeforeUpdate() 方法,所以这个方法被执行,并且向空的 DIV1 元素写入一条消息。

然后执行 componentDidUpdate() 方法并在空的 DIV2 元素中写入一条消息:

示例:

使用 getSnapshotBeforeUpdate() 方法找出更新前 state 对象的样子:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
    document.getElementById("div1").innerHTML =
    "Before the update, the favorite was " + prevState.favoritecolor;
  }
  componentDidUpdate() {
    document.getElementById("div2").innerHTML =
    "The updated favorite is " + this.state.favoritecolor;
  }
  render() {
    return (
      <div>
        <h1>My Favorite Color is {this.state.favoritecolor}</h1>
        <div id="div1"></div>
        <div id="div2"></div>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

componentDidUpdate

componentDidUpdate 方法是在组件在 DOM 中更新后调用的。

下面的示例可能看起来很复杂,但它所做的只是:

当组件安装时,它会以最喜欢的颜色"红色"呈现。

当组件已安装时,计时器会更改状态,并且颜色变为"黄色"。

这个动作触发了更新阶段,由于这个组件有一个 componentDidUpdate 方法,这个方法被执行并在空的 DIV 元素中写入一条消息 :

示例:

componentDidUpdate 方法在更新在 DOM 中呈现后被调用:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  componentDidUpdate() {
    document.getElementById("mydiv").innerHTML =
    "The updated favorite is " + this.state.favoritecolor;
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <div id="mydiv"></div>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

Unmounting

生命周期的下一个阶段是从 DOM 中移除一个组件,或者 unmounting,就像 React 喜欢的那样。

React 只有一个内置方法,在卸载组件时会被调用:

  • componentWillUnmount()

componentWillUnmount

componentWillUnmount 方法在组件即将从 DOM 中移除时被调用。

示例:

点击按钮删除表头:

class Container extends React.Component {
  constructor(props) {
    super(props);
    this.state = {show: true};
  }
  delHeader = () => {
    this.setState({show: false});
  }
  render() {
    let myheader;
    if (this.state.show) {
      myheader = <Child />;
    };
    return (
      <div>
      {myheader}
      <button type="button" onClick={this.delHeader}>Delete Header</button>
      </div>
    );
  }
}

class Child extends React.Component {
  componentWillUnmount() {
    alert("The component named Header is about to be unmounted.");
  }
  render() {
    return (
      <h1>Hello World!</h1>
    );
  }
}

ReactDOM.render(<Container />, document.getElementById('root'));