React组件的生命周期钩子

六、组件的生命周期

1. 理解

  • 组件从创建到死亡它会经历一些特定的阶段。

  • React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。

  • 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。

2. 生命周期流程(旧)

在这里插入图片描述

  • 初始化阶段: 由ReactDOM.render()触发—初次渲染

    • constructor()
    • componentWillMount()
    • render()
    • componentDidMount() ====> 常用:一般在这个钩子做一些初始化的事情,例如:开启定时器、发送网络请求、订阅消息
  • 更新阶段: 由组件内部this.setSate()或父组件render触发

    • shouldComponentUpdate()
    • componentWillUpdate()
    • render() ====> 必须使用的钩子
    • componentDidUpdate()
  • 卸载组件: 由ReactDOM.unmountComponentAtNode()触发

    • componentWillUnmount() ====> 常用:一般在这个钩子做一些收尾的事,例如:关闭定时器、取消订阅消息
  • 代码:

    // 创建组件
    class Count extends React.Component {
      // 构造器
      constructor(props) {
        console.log("Count --- constructor");
        super(props);
        // 初始化状态
        this.state = {
          count: 0,
        };
      }
    
      // 加一按钮
      add = () => {
        this.setState({
          count: ++this.state.count,
        });
      };
    
      // 卸载组件按钮的回调
      death = () => {
        ReactDOM.unmountComponentAtNode(document.getElementById("test"));
      };
    
      // 强制更新按钮的回调
      force = () => {
        this.forceUpdate();
      };
    
      // 组件将要挂载的钩子
      componentWillMount() {
        console.log("Count --- componentWillMount");
      }
    
      // 组件挂载完毕的钩子
      componentDidMount() {
        console.log("Count --- componentDidMount");
      }
    
      // 组件将要卸载的钩子
      componentWillUnmount() {
        console.log("Count --- componentWillUnmount");
      }
    
      // 控制组件更新的阀门
      shouldComponentUpdate() {
        // 不写,底层默认会补一个shouldComponentUpdate生命周期钩子,且默认返回true
        // 写了该生命周期钩子,以写的为准,返回true阀门开启,返回false阀门关闭
        console.log("Count --- shouldComponentUpdate");
        return true;
      }
    
      // 组件将要更新的的钩子
      componentWillUpdate() {
        console.log("Count --- componentWillUpdate");
      }
    
      // 组件更新完毕的钩子
      componentDidUpdate() {
        console.log("Count --- componentDidUpdate");
      }
    
      // 初始化渲染、状态更新之后调用
      render() {
        console.log("Count --- render");
        const { count } = this.state;
        return (
          <div>
            <h2>当前求和为:{count}</h2>
            <button onClick={this.add}>点我+1</button>
            <button onClick={this.death}>卸载组件</button>
            <button onClick={this.force}>
              不更改组件中任何状态中的数据,强制更新一下
            </button>
          </div>
        );
      }
    }
    
    // 父组件A
    class A extends React.Component {
      state = {
        carName: "奔驰",
      };
    
      changeCar = () => {
        this.setState({
          carName: "bwm",
        });
      };
    
      render() {
        console.log("A --- render");
        return (
          <div>
            <div>A组件</div>
            <button onClick={this.changeCar}>换车</button>
            <B carName={this.state.carName} />
          </div>
        );
      }
    }
    
    // 子组件B
    class B extends React.Component {
      // 组件将要接收新的props钩子
      componentWillReceiveProps(props) {
        // 第一次不算
        console.log("B --- componentWillReceiveProps", props);
      }
    
      // 控制组件更新的阀门
      shouldComponentUpdate() {
        // 不写,底层默认会补一个shouldComponentUpdate生命周期钩子,且默认返回true
        // 写了该生命周期钩子,以写的为准,返回true阀门开启,返回false阀门关闭
        console.log("B --- shouldComponentUpdate");
        return true;
      }
    
      // 组件将要更新的的钩子
      componentWillUpdate() {
        console.log("B --- componentWillUpdate");
      }
    
      // 组件更新完毕的钩子
      componentDidUpdate() {
        console.log("B --- componentDidUpdate");
      }
    
      render() {
        console.log("B --- render");
        return <div>B组件,接收到的车是:{this.props.carName}</div>;
      }
    }
    
    // 2.渲染组件到页面
    ReactDOM.render(<A />, document.getElementById("test"));
    

3. 生命周期流程(新)

在这里插入图片描述

  • 初始化阶段: 由ReactDOM.render()触发—初次渲染

    • constructor()
    • getDerivedStateFromProps ===>static
    • render() ====> 常用
    • componentDidMount() ====> 常用:一般在这个钩子做一些初始化的事情,例如:开启定时器、发送网络请求、订阅消息
  • 更新阶段: 由组件内部this.setSate()或父组件重新render触发

    • getDerivedStateFromProps()
    • shouldComponentUpdate()
    • render()
    • getSnapshotBeforeUpdate
    • componentDidUpdate()
  • 卸载组件: 由ReactDOM.unmountComponentAtNode()触发

    • componentWillUnmount() ====> 常用:一般在这个钩子做一些收尾的事,例如:关闭定时器、取消订阅消息
  • 代码如下:

    // 创建组件
    class Count extends React.Component {
      // 构造器
      constructor(props) {
        console.log("Count --- constructor");
        super(props);
        // 初始化状态
        this.state = {
          count: 0,
        };
      }
    
      // 加一按钮
      add = () => {
        this.setState({
          count: this.state.count + 1,
        });
      };
    
      // 卸载组件按钮的回调
      death = () => {
        ReactDOM.unmountComponentAtNode(document.getElementById("test"));
      };
    
      // 强制更新按钮的回调
      force = () => {
        this.forceUpdate();
      };
    
      // 若state的同名属性值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
      static getDerivedStateFromProps(props, state) {
        console.log("Count --- getDerivedStateFromProps", props, state);
        return null;
      }
    
      // 在更新之前获取快照
      getSnapshotBeforeUpdate(preProps, preState) {
        console.log("Count --- getSnapshotBeforeUpdate");
        return "xzq";
      }
    
      // 组件挂载完毕的钩子
      componentDidMount() {
        console.log("Count --- componentDidMount");
      }
    
      // 组件将要卸载的钩子
      componentWillUnmount() {
        console.log("Count --- componentWillUnmount");
      }
    
      // 控制组件更新的阀门
      shouldComponentUpdate() {
        // 不写,底层默认会补一个shouldComponentUpdate生命周期钩子,且默认返回true
        // 写了该生命周期钩子,以写的为准,返回true阀门开启,返回false阀门关闭
        console.log("Count --- shouldComponentUpdate");
        return true;
      }
    
      // 组件更新完毕的钩子
      componentDidUpdate(preProps, preState, snapValue) {
        // 此处若是add里面的修改count是'count: ++this.state.count' 那么会导致preState等于当前state
        console.log("Count --- componentDidUpdate", preProps, preState, snapValue);
      }
    
      // 初始化渲染、状态更新之后调用
      render() {
        console.log("Count --- render");
        const { count } = this.state;
        return (
          <div>
            <h2>当前求和为:{count}</h2>
            <button onClick={this.add}>点我+1</button>
            <button onClick={this.death}>卸载组件</button>
            <button onClick={this.force}>
              不更改组件中任何状态中的数据,强制更新一下
            </button>
          </div>
        );
      }
    }
    
    // 2.渲染组件到页面
    ReactDOM.render(<Count count={199} />, document.getElementById("test"));
    
  • getSnapshotBeforeUpdate的使用场景

    • 需求描述

      • 展示一个新闻加载的案例

      • 每隔一秒增加一条新闻在顶部

      • 保持当前看到的新闻不会窜动

        在这里插入图片描述

    • 代码如下:

      class NewsList extends React.Component {
        state = {
          newsArr: [],
        };
      
        componentDidMount() {
          setInterval(() => {
            // 获取原状态
            const { newsArr } = this.state;
            // 模拟一条数据
            const news = "新闻" + (newsArr.length + 1);
            // 更新状态
            this.setState({
              // 新生成的新闻在前
              newsArr: [news, ...newsArr],
            });
          }, 1000);
        }
      
        getSnapshotBeforeUpdate(preProps, preState) {
          return this.refs.list.scrollHeight;
        }
        componentDidUpdate(preProps, preState, snapValue) {
          // 每次添加一条新闻就让滚动条往下走一条新闻的高度,实现内容不会窜动
          this.refs.list.scrollTop += this.refs.list.scrollHeight - snapValue;
        }
      
        render() {
          return (
            <div className="list" ref="list">
              {this.state.newsArr.map((x, index) => {
                return (
                  <div className="news" key={index}>
                    {x}
                  </div>
                );
              })}
            </div>
          );
        }
      }
      
      // 2.渲染组件到页面
      ReactDOM.render(<NewsList />, document.getElementById("test"));
      

4. 重要的勾子

  • render:初始化渲染或更新渲染调用
  • componentDidMount:开启监听, 发送ajax请求
  • componentWillUnmount:做一些收尾工作, 如: 清理定时器

5. 即将废弃的勾子

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

注意:现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嘎嘎油

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

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

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

打赏作者

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

抵扣说明:

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

余额充值