0206旧版生命周期-组件-React

1 前言

React生命周期描述了组件在创建、更新和销毁过程中所经历的不同阶段。这些生命周期方法可以在组件的代码中定义并实现,以便在适当的时候执行自定义操作。

现在我们先学习旧版(16.x及以前)的生命周期函数,然后在对比学习新版(17.x及以后)声明周期方法。

以下是React 16及之前版本中组件的生命周期图示:

在这里插入图片描述

2 示例引出生命周期函数

示例效果如下图1-1所示:

在这里插入图片描述

  • ​ 字体透明度逐渐变淡重复执行
  • 点击移除按钮,组件移除

代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>1201_引出生命周期</title>
</head>

<body>
  <div id="test"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    /**
     * 创建组件
     *  生命周期函数:生命周期钩子函数
     */
    class Life extends React.Component {
      // 初始化状态
      state = {
        opacity: 1 // 透明度
      }

      /**
       * 移除组件
       */
      remove = () => {
        // 卸载组件
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
      }

      /**
       * 组件挂载完毕
       */
      componentDidMount() {
        // 实现字体逐渐变淡效果
        this.timer = setInterval(() => {
          let {opacity} = this.state
          // 字体透明度为0即透明后,重新赋值1
          if (opacity <= 0) {
            opacity = 1
          }
          opacity -= 0.1
          this.setState({opacity})
        }, 200);
      }

      /**
       * 组件卸载之前
       */
      componentWillUnmount() {
        // 清除定时器
        clearInterval(this.timer)
      }

      /**
       * 初始化渲染,状态更新重新渲染
       */
      render() {
        return (
          <div>
            <h2 style={{opacity: this.state.opacity}}>学习React组件生命周期</h2><br/>
            <button onClick={this.remove}>移除</button>
          </div>
        )
      }
      
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Life/>, document.getElementById('test'))

  </script>
</body>

</html>
  • ReactDOM.unmountComponentAtNode()为卸载组件API
  • 定时器要求组件挂载之后创建,创建一次;在组件卸载之前清除。
  • componentDidMount():组件挂载之后执行
  • componentWillUnmount():组件卸载之前执行
  • React还提供了很多其他生命周期函数

生命周期函数也称生命周期钩子函数,生命周期钩子。React会在合适的时间点,调用相应的生命周期函数。

3 生命周期

React 16之前的生命周期被分为三个阶段:

  • 挂载(Mounting)阶段
  • 更新(Updating)阶段
  • 卸载(Unmounting)阶段

3 挂载阶段

挂载阶段(Mounting):这是组件在实例化并插入DOM中的过程。在这个阶段,React会依次调用以下方法:

  • constructor():组件的构造函数,在组件创建时调用。
  • componentWillMount():组件插入DOM之前被调用。
  • render():生成虚拟DOM并返回JSX。
  • componentDidMount():组件插入DOM后被调用。

示例代码如下3-1所示:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>1202_生命周期()</title>
</head>

<body>
  <div id="test"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    /**
     * 创建组件
     *  生命周期函数:生命周期钩子函数
     */
    class Count extends React.Component {
      constructor(props) {
        console.log('Count === constructor');
        super(props)
        // 初始化状态
        this.state = {
          count: 1 // 计数
        }
      }


      /**
       * +1
       */
      add = () => {
        this.setState({count: this.state.count + 1})
      }

      /**
       * 卸载组件
       */
       remove = () => {
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
      }

      /**
       * 组件将要挂载
       */
      componentWillMount() {
        console.log('Count === componentWillMount');
      }

      /**
       * 组件挂载完毕
       */
      componentDidMount() {
        console.log('Count === componentDidMount');
      }

      /**
       * 组件卸载之前
       */
      componentWillUnmount() {
        console.log('Count === componentWillUnmount');
      }

      /**
       * 初始化渲染,状态更新重新渲染
       */
      render() {
        console.log('Count === render');
        const { count } = this.state
        return (
          <div>
            <h2>当前计数:{count}</h2><br />
            <button onClick={this.add}>点我+1</button>
          </div>
        )
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Count />, document.getElementById('test'))

  </script>
</body>

</html>

如下图3-1所示:

在这里插入图片描述

4 更新阶段

在更新阶段,组件的props或state被修改,导致重新渲染。以下是更新阶段的生命周期方法:

  • componentWillReceiveProps():用于在组件接收到新的 props 时进行操作。它会在组件接收到新的 props 之前被调用,并且可以根据新的 props 来更新组件的状态。
  • shouldComponentUpdate(nextProps, nextState):在组件更新时调用,决定是否需要重新渲染组件,可以优化性能,默认返回true。
  • componentWillUpdate():作用是让组件在更新之前进行一些准备工作,例如计算一些属性或状态的值,或者更新组件之前进行一些必要的清理操作。但需要注意的是,在此方法中不能直接更新组件的状态或DOM,因为此时组件尚未被更新。
  • render():在组件更新时调用,返回虚拟DOM,用于渲染到页面。
  • componentDidUpdate(prevProps, prevState, snapshot):在组件更新后调用,可以执行DOM操作或发起网络请求等操作。

第一种更新,setState()引起的更新

  • shouldComponentUpdate返回true与返回false的区别

以代码3-1为例,额外添加shouldComponentUpdate函数代码如下;

shouldComponentUpdate(nextProps, nextState) {
  console.log('count === shouldComponentUpdate :', nextProps, '----', nextState);
  return true;
}

返回true时,如下图4-1所示:

在这里插入图片描述

返回false时,如下图4-2所示:

在这里插入图片描述

声明周期函数shouldComponentUpdate()默认返回true,该方法之后的生命周期函数正常执行;当返回false时,不在执行后续的生命周期函数。

第二种更新,执行forceUpdate()后的更新

​ 示例,上述基础在添加一个按钮,点击执行forceUpdate,示例代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>1203_updating-生命周期(旧)</title>
</head>

<body>
  <div id="test"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    /**
     * 创建组件
     *  生命周期函数:生命周期钩子函数
     */
    class Count extends React.Component {
      constructor(props) {
        console.log('Count === constructor');
        super(props)
        // 初始化状态
        this.state = {
          count: 1 // 计数
        }
      }


      /**
       * +1
       */
      add = () => {
        this.setState({count: this.state.count + 1})
      }

      /**
       * 不更新状态,强制更新
       */
      force = () => {
        console.log('Count ==== forceUpate');
        this.forceUpdate()
      }

      /**
       * 卸载组件
       */
       remove = () => {
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
      }

      /**
       * 组件将要挂载
       */
      componentWillMount() {
        console.log('Count === componentWillMount');
      }

      /**
       * 组件挂载完毕
       */
      componentDidMount() {
        console.log('Count === componentDidMount');
      }
      
      /**
       * 组件是否应该被更新
       */
      shouldComponentUpdate(nextProps, nextState) {
        console.log('count === shouldComponentUpdate :', nextProps, '----', nextState);
        return true;
      }

      /**
       * 组件将要被更新之前
       */
      componentWillUpdate(nextProps, nextState) {
        console.log('count === componentWillUpdate :', nextProps, '----', nextState);
      }

      /**
       * 组件将要被更新之后
       */
       componentDidUpdate(prevProps, prevState) {
        console.log('count === componentDidUpdate :', prevProps, '----', prevState);
      }

      /**
       * 组件卸载之前
       */
      componentWillUnmount() {
        console.log('Count === componentWillUnmount');
      }

      /**
       * 初始化渲染,状态更新重新渲染
       */
      render() {
        console.log('Count === render');
        const { count } = this.state
        return (
          <div>
            <h2>当前计数:{count}</h2><br />
            <button onClick={this.add}>点我+1</button><br/>
            <button onClick={this.force}>不更改状态强制更新</button>
            </div>
        )
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Count />, document.getElementById('test'))

  </script>
</body>

</html>

点击示例效果如下图4-3所示:

在这里插入图片描述

执行组件的forceUpdate()方法,不受shouldComponentUpdate函数的影响。

第三种更新,父子组件中父组件更新传值引起的子组件更新。

实例代码如下4-4代码所示:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>1204_parent-son-生命周期(旧)</title>
</head>

<body>
  <div id="test"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    /**
     * 创建组件
     *  生命周期函数:生命周期钩子函数
     */
    class SuperCar extends React.Component {
      state = {carName: '第一代奔驰'}

      changeCar = () => {
        this.setState({carName: '第二代奔驰'})
      }
      
      

      /**
       * 初始化渲染,状态更新重新渲染
       */
      render() {
        
        const { carName } = this.state
        return (
          <div>
            <h2>我的父组件</h2><br />
            <button onClick={this.changeCar}>换车</button><br/>
            <SubCar carName={carName}/>
            </div>
        )
      }
    }

    class SubCar extends React.Component {
      
      
      /**
       * 组件将要接受更新props
       */
       componentWillReceiveProps(nextProps) {
        console.log('SubCar === componentWillReceiveProps', '---', nextProps);
      }
      
      /**
       * 组件将要挂载
       */
       componentWillMount() {
        console.log('SubCar === componentWillMount');
      }

      /**
       * 组件挂载完毕
       */
      componentDidMount() {
        console.log('SubCar === componentDidMount');
      }
      
      /**
       * 组件是否应该被更新
       */
      shouldComponentUpdate(nextProps, nextState) {
        console.log('SubCar === shouldComponentUpdate :', nextProps, '----', nextState);
        return true;
      }

      /**
       * 组件将要被更新之前
       */
      componentWillUpdate(nextProps, nextState) {
        console.log('SubCar === componentWillUpdate :', nextProps, '----', nextState);
      }

      /**
       * 组件将要被更新之后
       */
       componentDidUpdate(prevProps, prevState) {
        console.log('SubCar === componentDidUpdate :', prevProps, '----', prevState);
      }

      /**
       * 组件卸载之前
       */
      componentWillUnmount() {
        console.log('SubCar === componentWillUnmount');
      }

      render() {
        console.log('SubCar === render');
        return (
        <div>
          <h2>我是子组件,接收到的是{this.props['carName']}</h2>
         </div>
        )
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<SuperCar />, document.getElementById('test'))

  </script>
</body>

</html>

效果如下图4-4所示:

在这里插入图片描述

componentWillReceiveProps默认第一次不会执行,再次更新props才会执行。

5 卸载阶段

通过ReactDOM.unmountComponentAtNode(组件)卸载组件,在卸载之前回调生命周期函数componentWillUnmount()

在#2中有示例,这里不在演示。

目前旧版本React组件的生命周期讲解完毕,下面我们对比讲解下新版React组件的生命周期。

后记

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/react-study

参考:

[1]尚硅谷React教程(2022加更,B站超火react教程)[CP/OL].2020-12-15.p37-p42.

[2]React官网[CP/OL].

[2]ChatGPT[CP/OL].

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值