React生命周期

1,000 阅读4分钟

前言

React新版生命周期,个人语言描述有问题可以反馈>v<

import React, { Component } from 'react'

export default class LifeCycle extends Component {
    //// props = {age:10,name:'计数器'}
  static defaultProps = {
      name:'计数器'
  }
  constructor(props){
      //Must call super constructor in derived class before accessing 'this' or returning from derived constructor
    super();//this.props = props;
    this.state = {number:0,users:[]};//初始化默认的状态对象
    console.log('1. constructor 初始化 props and state');
  
  }  
  //componentWillMount在渲染过程中可能会执行多次
  componentWillMount(){
    console.log('2. componentWillMount 组件将要挂载');
    //localStorage.get('userss');
  }
  //componentDidMount在渲染过程中永远只有执行一次
  //一般是在componentDidMount执行副作用,进行异步操作
  componentDidMount(){
    console.log('4. componentDidMount 组件挂载完成');
    fetch('https://api.github.com/users').then(res=>res.json()).then(users=>{
        console.log(users);
        this.setState({users});
    });
  }
  shouldComponentUpdate(nextProps,nextState){
    console.log('Counter',nextProps,nextState);
    console.log('5. shouldComponentUpdate 询问组件是否需要更新');
    return true;
  }
  componentWillUpdate(nextProps, nextState){
    console.log('6. componentWillUpdate 组件将要更新');
  }
  componentDidUpdate(prevProps, prevState)){
    console.log('7. componentDidUpdate 组件更新完毕');
  }
  add = ()=>{
      this.setState({number:this.state.number});
  };
  render() {
    console.log('3.render渲染,也就是挂载')
    return (
      <div style={{border:'5px solid red',padding:'5px'}}>
        <p>{this.props.name}:{this.state.number}</p>
        <button onClick={this.add}>+</button>
        <ul>
            {
                this.state.users.map(user=>(<li>{user.login}</li>))
            }
        </ul>
        {this.state.number%2==0&&<SubCounter number={this.state.number}/>}
      </div>
    )
  }
}
class SubCounter extends Component{
    constructor(props){
        super(props);
        this.state = {number:0};
    }
    componentWillUnmount(){
        console.log('SubCounter componentWillUnmount');
    }
    //调用此方法的时候会把新的属性对象和新的状态对象传过来
    shouldComponentUpdate(nextProps,nextState){
        console.log('SubCounter',nextProps,nextState);
        if(nextProps.number%3==0){
            return true;
        }else{
            return false;
        }
    }
    //componentWillReceiveProp 组件收到新的属性对象
    componentWillReceiveProps(){
      console.log('SubCounter 1.componentWillReceiveProps')
    }
    render(){
        console.log('SubCounter  2.render')
        return(
            <div style={{border:'5px solid green'}}>
                <p>{this.props.number}</p>
            </div>
        )
    }
}

React生命周期做了什么以及能做什么?

初始化

  • defaultProps()、propTypes()

    • 查看是否设置了默认属性以及属性校验
  • constructor (异步请求有特殊情况的话也可以放这里)

    • 初始化属性和状态
    • react组件的构造函数在挂载之前被调用。 super() 如果类进行了继承的话需要调用这个
    • 在这块不能调用setState
  • getDerivedStateFromProps(props,state)

    • 接收传入的props,映射到state
    • 将父组件传递过来的 props 映射 到子组件的 state 上面,这样组件内部就不用再通过 this.props.xxx 获取属性值了,统一通过 this.state.xxx 获取。
    • state={a:this.props.a} props的a发生变化时 会影响到state触发更新
    • 当组件的state需要根据props来改变的时候可调用此方法 这个方法是在 render() 前会被执行,每次触发render前,都会触发此方法。 需要配置 constructor(props){super(props) ,this.state={props}} 才能打印出值
  • render() 创建虚拟dom进行diff算法

    • 创建虚拟dom,进行diff算法,更新dom树都在此进行。 此时就不能更改state了。
    • 必须要有返回值,一般为null
  • componentDidMount() (异步请求放这里)

    • 虚拟DOM挂载到页面代替真实DOM
    • 组件挂载到DOM后调用,且只会被调用一次
    • 组件开始运行 ,state可以被修改, 组件更新时
  • getDerivedStateFromProps(props,state)

    • 接收传入的props,映射到state
    • 更新时再次调用该钩子 父组件传递过来的 props 映射 到子组件的 state
  • shouldComponentUpdate(nextProps, nextState) 新的属性 , 新的状态

    • 旧状态和新状态对比判断是否需要更新组件? true of false
    • 用当前的this.state/props和nextProps/state新的进行判断 此方法通过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新停止,以此可用来减少组件的不必要渲染,优化组件性能。
    • 默认返回值 return true false就不会渲染更新视图
  • render()

    • 更新虚拟DOM , 覆盖真实DOM,完成视图渲染
  • getSnapShotBeforeUpdate(prevProps,prevState) 快照 get(获取) SnapShot(快照)

    • 触发时间
      • update发生的时候(更新 DOM 和 refs 之前)
      • 在render之后,在组件dom渲染之前;
    • 接收父组件传递过来的 props 和组件之前的状态,此生命周期钩子必须有返回值,返回值将作为第三个参数传递给componentDidUpdate。必须和 componentDidUpdate 一起使用,否则会报错
    • 作用:在组件更新 DOM 和 refs 之前,从 DOM 中捕获一些信息(例如滚动位置)必须有返回值 它能让你,在组件更新 DOM 和 refs 之前,它能让你从 DOM 中捕获一些信息9例如滚动位置)必须有返回值
  • componentDidUpdate(prevProps,prevState,snaPshot) 接收快照 根据标识来更新状态

    • 组件更新完毕
    • 组件更新结束之后执行,在初始化render时不执行
    • 避免使用setState,如果componentDidMount 也setState 会进行死循环

组件卸载

  • componentWillUnmount() ,可以在这里执行一些清理工作

旧版生命周期

相比较于新版生命周期,官方去掉了一些可能产生问题的生命周期,且新增了快照能够获取更新钱的状态

新版对比旧版

  • 废除componentWillMount(避免bug)
    • 新增 : 用getDerivedStateFromProps(props,state) 代替
  • 废除componentWillReceiveProps(有bug)
  • 废除componentWillUpdate
  • 新增:getSnapshotBeforeUpdate

父子之间组件触发顺序

over

本文使用 mdnice 排版