React生命周期

生命周期钩子

生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子

  1. 组件从创建到死亡它会经历一些特定的阶段
  2. React组件中包含一系列钩子函数(生命周期回调函数),会再特定时刻调用。
  3. 我们再定义组件时,会在特定的生命周期回调函数中,做特定的工作。

生命周期流程图(旧v16.8.4)

生命周期

挂载时的生命周期

    <script type="text/babel">
      // 创建组件
      class Count extends React.Component {
        // 构造器
        constructor(props) {
          console.log("constructor");
          super(props);
          this.state = {
            count: 0,
          };
        }
        // 组件将要挂载的钩子
        componentWillMount() {
          console.log("componentWillMount");
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log("componentDidMount");
        }
        add = () => {
          let { count } = this.state;
          count += 1;
          this.setState({ count: count });
        };
        render() {
          console.log("render");
          return (
            <div>
              <h2>`当前求和为{this.state.count}`</h2>
              <button onClick={this.add}>点我加一</button>
            </div>
          );
        }
      }
      ReactDOM.render(<Count />, document.getElementById("test"));
    </script>

更新时的生命周期 —— setState()

  • shouldComponentUpdate(){ return true;}
    如果写了,就必须有返回值,如果没写,React会自动给补上一个返回值为true的。
    <script type="text/babel">
      // 创建组件
      class Count extends React.Component {
        // 构造器
        constructor(props) {
          console.log("constructor");
          super(props);
          this.state = {
            count: 0,
          };
        }
        // 组件将要挂载的钩子
        componentWillMount() {
          console.log("componentWillMount");
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log("componentDidMount");
        }
        // 组件将要被卸载
        componentWillUnmount() {
          console.log("componentWillUnmount");
        }
        //卸载组件按钮的回调
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById("test"));
        };
        // 控制组件更新的阀门
        shouldComponentUpdate() {
          console.log("shouldComponentUpdate");
          return true;
        }
        // 组件将要更新的钩子
        componentWillUpdate() {
          console.log("componentWillUpdate");
        }
        //组件更新完毕的钩子
        componentDidUpdate() {
          console.log("componentDidUpdate");
        }
        add = () => {
          let { count } = this.state;
          count += 1;
          this.setState({ count: count });
        };
        render() {
          console.log("render");
          return (
            <div>
              <h2>`当前求和为{this.state.count}`</h2>
              <button onClick={this.add}>点我加一</button>
              <button onClick={this.death}>点我消失</button>
            </div>
          );
        }
      }
      ReactDOM.render(<Count />, document.getElementById("test"));
    </script>

更新时的生命周期 —— forceUpdate()

  • 不对状态进行任何修改,调用forceUpdate()也可以更新。不受到shouldComponentUpdate()的限制
    <script type="text/babel">
      // 创建组件
      class Count extends React.Component {
        // 构造器
        constructor(props) {
          console.log("constructor");
          super(props);
          this.state = {
            count: 0,
          };
        }
        // 组件将要挂载的钩子
        componentWillMount() {
          console.log("componentWillMount");
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log("componentDidMount");
        }
        // 组件将要被卸载
        componentWillUnmount() {
          console.log("componentWillUnmount");
        }
        //卸载组件按钮的回调
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById("test"));
        };
        // 控制组件更新的阀门
        shouldComponentUpdate() {
          console.log("shouldComponentUpdate");
          return true;
        }
        // 组件将要更新的钩子
        componentWillUpdate() {
          console.log("componentWillUpdate");
        }
        //组件更新完毕的钩子
        componentDidUpdate() {
          console.log("componentDidUpdate");
        }

        force = () => {
          this.forceUpdate();
        };

        add = () => {
          let { count } = this.state;
          count += 1;
          this.setState({ count: count });
        };
        render() {
          console.log("render");
          return (
            <div>
              <h2>`当前求和为{this.state.count}`</h2>
              <button onClick={this.add}>点我加一</button>
              <button onClick={this.death}>点我消失</button>
              <button onClick={this.force}>点我强制刷新</button>
            </div>
          );
        }
      }
      ReactDOM.render(<Count />, document.getElementById("test"));
    </script>

父组件的更新流程

  • 父组件一旦重新render,子组件就会响应componentWillReceiveProps()。【第一次传的不算】
      class A extends React.Component {
        // 初始化状态
        state = {
          car: "奔驰",
        };
        changeCar = () => {
          this.setState({ car: "奥拓" });
        };
        render() {
          return (
            <div>
              <div>我是A组件</div>
              <button onClick={this.changeCar}>换车</button>
              <B carName={this.state.car} />
            </div>
          );
        }
      }
      class B extends React.Component {
        // 控制组件更新的阀门
        shouldComponentUpdate() {
          console.log("shouldComponentUpdate");
          return true;
        }
        // 组件将要更新的钩子
        componentWillUpdate() {
          console.log("componentWillUpdate");
        }
        //组件更新完毕的钩子
        componentDidUpdate() {
          console.log("componentDidUpdate");
        }

        // 组件将要接收新的props的钩子
        componentWillReceiveProps(props) {
          console.log("componentWillReceiveProps", props);
        }
        render() {
          console.log("render");
          return <div>我是B组件,接收到的车是{this.props.carName}</div>;
        }
      }
      ReactDOM.render(<A />, document.getElementById("test"));

总结

  1. 初始化阶段:由React.DOM.render()出发——初次渲染
  • constructor()
  • componentWillMount()
  • render
  • componentDidMount() —— 常用
    一般在这个钩子中做一些初始化的事,例如:烤漆定时器,发送网络请求,订阅消息
  1. 更新阶段:由组件内部this.setState()或父组件重新render触发
  • shouldComponentUpdate()
  • componentWillUpdate()
  • render()
  • componentDidUpdate()
  1. 卸载组件:由React.unmountComponentAtNode()出发
  • componentWillUnmount() —— 常用
    一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

生命周期(新v17.0.1)

新版本中可以用旧的钩子,但是会有警告
新的生命周期

  1. 新版本中,三个方法必须加上前缀UNSAFE_
  • componentWillMount() => UNSAFE_componentWillMount()
  • componentWillUpdate() => UNSAFE_componentWillUpdate()
  • componentWillReceiveProps() => UNSAFE_componentWillReceiveProps()
  1. 新提出两个钩子:
  • getDerivedStateFromProps()
  • getSnapshotBeforeUpdate()
    但是用的地方十分罕见
    <script type="text/babel">
      // 创建组件
      class Count extends React.Component {
        // 构造器
        constructor(props) {
          console.log("constructor");
          super(props);
          this.state = {
            count: 0,
          };
        }
        // 组件将要挂载的钩子
        UNSAFE_componentWillMount() {
          console.log("componentWillMount");
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log("componentDidMount");
        }
        // 组件将要被卸载
        componentWillUnmount() {
          console.log("componentWillUnmount");
        }
        //卸载组件按钮的回调
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById("test"));
        };
        // 控制组件更新的阀门
        shouldComponentUpdate() {
          console.log("shouldComponentUpdate");
          return true;
        }
        // 组件将要更新的钩子
        UNSAFE_componentWillUpdate() {
          console.log("componentWillUpdate");
        }
        //组件更新完毕的钩子
        componentDidUpdate() {
          console.log("componentDidUpdate");
        }

        force = () => {
          this.forceUpdate();
        };

        add = () => {
          let { count } = this.state;
          count += 1;
          this.setState({ count: count });
        };
        render() {
          console.log("render");
          return (
            <div>
              <h2>`当前求和为{this.state.count}`</h2>
              <button onClick={this.add}>点我加一</button>
              <button onClick={this.death}>点我消失</button>
              <button onClick={this.force}>点我强制刷新</button>
            </div>
          );
        }
      }
//父组件A
      class A extends React.Component {
        // 初始化状态
        state = {
          car: "奔驰",
        };
        changeCar = () => {
          this.setState({ car: "奥拓" });
        };
        render() {
          return (
            <div>
              <div>我是A组件</div>
              <button onClick={this.changeCar}>换车</button>
              <B carName={this.state.car} />
            </div>
          );
        }
      }
      //子组件B
      class B extends React.Component {]
      	UNSAFE_componentWillReceiveProps(){
      	}
        render() {
          console.log("render");
          return <div>我是B组件,接收到的车是{this.props.carName}</div>;
        }
      }
      ReactDOM.render(<Count />, document.getElementById("test"));
      ReactDOM.render(<Count />, document.getElementById("test"));
    </script>

getDerivedStateFromProps()

  • 不是给实例调用,在定义前要加static,加在类自身上,并且必须返回一个状态对象或者null
  • 从props获得派生的状态,这个状态无法被改变
  • 此方法适用于十分罕见的用例,即state的值在任何时候都取决于props
  • 派生状态会导致代码冗余,并使组件难以维护
<script type="text/babel">
      // 创建组件
      class Count extends React.Component {
        // 构造器
        constructor(props) {
          console.log("constructor");
          super(props);
          this.state = {
            count: 0,
          };
        }
        //若任何时候state的值在任何时候都取决于props,则可以用getDerivedStateFromProps
        static getDerivedStateFromProps(props) {
          console.log("getDerivedStateFromProps");
          return props;
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log("componentDidMount");
        }
        // 组件将要被卸载
        componentWillUnmount() {
          console.log("componentWillUnmount");
        }
        //卸载组件按钮的回调
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById("test"));
        };
        // 控制组件更新的阀门
        shouldComponentUpdate() {
          console.log("shouldComponentUpdate");
          return true;
        }

        //组件更新完毕的钩子
        componentDidUpdate() {
          console.log("componentDidUpdate");
        }

        force = () => {
          this.forceUpdate();
        };

        add = () => {
          let { count } = this.state;
          count += 1;
          this.setState({ count: count });
        };
        render() {
          console.log("render");
          return (
            <div>
              <h2>`当前求和为{this.state.count}`</h2>
              <button onClick={this.add}>点我加一</button>
              <button onClick={this.death}>点我消失</button>
              <button onClick={this.force}>点我强制刷新</button>
            </div>
          );
        }
      }
      ReactDOM.render(<Count count="199" />, document.getElementById("test"));
    </script>

getSnapshotBeforeUpdate()

  • 在最近一次渲染输出(提交到DOM节点)之前调用,它使得组件能在发生更改之前从DOM中捕获一些信息(例如:滚动位置)。此声明周期的任何返回值将作为参数传递给componentDidUpdate()
  • 必须有返回值,要么一个快照,要么一个null
  • 任何值都可以作为快照值
  • componentDidUpdate(preProps,preState,snapShot)可以接受三个参数,一个是之前传递的props,一个是之前的state,还有快照值
  • getDerivedStateFromProps(props,state)接收当前的props和state
    <script type="text/babel">
      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() {
          return this.refs.list.scrollHeight;
        }
        componentDidUpdate(preProps, preState, height) {
          this.refs.list.scrollTop += this.refs.list.scrollHeight - height;
        }
        render() {
          return (
            <div className="list" ref="list">
              {this.state.newsArr.map((n, index) => {
                return (
                  <div key={index} className="news">
                    {n}
                  </div>
                );
              })}
            </div>
          );
        }
      }
      ReactDOM.render(<NewsList />, document.getElementById("test"));
    </script>

总结

  1. 初始化阶段:由ReactDOM.render()触发——初次渲染
  • constructor()
  • getDerivedStateFromProps()
  • render()
  • componentDidMount() —— 常用
    一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  1. 更新阶段:由组件内部this.setState()或父组件重新render触发
  • getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()
  1. 卸载组件:由ReactDOM.unmountComponentAtNode()触发
  • componentWillUnmount() —— 常用
    一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值