React生命周期以及17.0版本新生命周期

React的生命周期:

construtor

(1)完成组件的初始化,用来定义当前组件所需要的一些状态,这些状态定义在this.state中; (2)当前生命周期函中必须书写super,否则this的指向会发生错误而报错; (3)在当前生命周期中是访问不到props属性的,如果要访问必须在super以及construtor中添加参数props;

componentWillMount(在17.0中已经废除掉了):

挂载前: (1)在服务端渲染时,可以进行前后端数据的请求; (2)可以在数据第一次被渲染的时候做数据的修改; (3)在当前生命周期中尽量不要使用this.setState,因为当前生命周期函数执行完毕后,会自动执行render函数; (4)可以将外部的数据转换为内部的数据;

render:

渲染时: (1)当前生命周期用来进行数据与视图的结合; (2)render函数第一次执行的时候会将渲染的数据在内存中保存一份(缓存),当第二次数据发生改变后,会将这次新的虚拟DOM与缓存中的虚拟DOM进行对比即Diff算法; (3)只要this.state/this.props发生了改变,那么render函数就会执行

componentDidMount

挂载后: (1)当前生命周期可以做前后端数据的交互(常用来向后端发送请求数据); (2)可以在当前生命周期获取到真实的DOM,通过this.refs来获取当前DOM元素

//挂载真实DOM的方法:
ref='h2' 获取DOM元素 this.refs.h2
ref={(el) => { this.dom = el }} 

(3)一般情况下在当前生命周期中做一些插件的实例化,如new Swiper();

componentWillReceiveProps(newProps) (在17.0中已经废除掉了)

(1)当this.props发生改变的时候就会执行当前函数; (2)当前函数中会有一个参数,这个参数是一个新的props; (3)在当前生命周期函数中可以对新的props进行修改

shouldComponentUpdate(newProps,newState)

(1)当this.state/this.props被修改的时候会执行当前生命周期函数; (2)当前生命周期函数执行时必须返回一个true或false值,该值决定了render函数是否执行,若返回值为true则render函数执行,否则render函数不会执行; (3)如果返回值为true则下面的生命周期函数会执行,否则下面的生命周期函数均不会执行; (4)当前生命周期函数中有两个参数,一个是新的props,一个是新的state; (5)当前生命周期特别重要,因为可以做React的性能优化(根据比较新旧state/props进行对比来决定是否需要执行渲染); (6)当前生命周期决定的是render函数是否执行,而不是数据是否修改

componentWillUpdate(newProps,newState) (在17.0中已经废除掉了)

更新前: (1)在当前生命周期中可以对更新的数据做最后的修改; (2)当前生命周期函数中有两个参数,一个是新的props,一个是新的state

componentDidUpdate

更新后: (1)当前生命周期中可以获取到数据更新后最新的DOM结构; (2)注意当前生命周期会执行多次,所以当需要做业务逻辑操作时一定要判断;

componentWillUnmount

卸载: (1)事件的解绑;(2)数据的移除等操作 总结: 在初次渲染时执行的生命周期函数有: construtor -> componentWillMount -> render -> componentDidMount 当this.props/this.state发生改变的时候执行的生命周期函数: this.props发生改变:componentWillReceiveProps -> ShouldComponentUpdate -> ComponentWillUpdate -> render -> ComponentDidUpdate this.state发生改变:ShouldComponentUpdate -> ComponentWillUpdate -> render -> ComponentDidUpdate React中哪些生命周期函数会执行一次,哪些会执行多次 多次:componentWillReceiveProps;shouldComponentUpdate;ComponentWillUpdate;render;ComponentDidUpdate 一次:construtor;componentWillMount;componentDidMount;componentWillUnmount 在17.0版本中废除的生命周期函数有componentWillMount,componentWillReceiveProps,componentWillUpdate,与此同时增加的生命周期函数有:

getDerivedStateFromProps(nextProps,preState)

(1)根据传入的props来更新state; (2)该方法是一个static(静态)方法,意味着该方法属于React.Component类的方法,所以方法内是无法使用this的,也就意味着无法使用this.setState来更新state,所以该方法是通过直接返回对象的形式来更新state,如果某些props的情况下不需要更新state,直接返回null即可。实际上这个方法和componentDidUpdate搭配使用,就能覆盖componentWillReceiveProps的所有使用场景了。

static getDerivedStateFromProps(nextProps,prevState) {
    if(nextProps.pos !== prevState.pos) {
        return {
            pos:nextProps.pos
        }
    }
    return null;
}

getSnapshotBeforeUpdate

(1)在更新之前获取组件的快照,在组件更新前触发; (2)它的返回值会作为第三个参数传递给后面的componentDidUpdate参数中,和componentDidUpdate一起使用,就能覆盖掉componentWillUpdate的所有使用场景了。

class ScrollingList extends React.Component {
    listRef = null;

    getSnapshotBeforeUpdate(prevProps,prevState) {
        if(prevProps.list.length < this.props.list.length) {
            return {
                this.listRef.scrollHeight - this.listRef.scrollTop
            }
        }
        return null;
    }

    componentDidUpdate(prevProps,prevState,snapshot) {
        if(snapshot !== null) {
            this.listRef.scrollTop = this.listRef.scrollHeight - snapshot;
        }
    }

    render() {
        return (
            <div ref = {this.setListRef}> </div>
        );
    }

    setListRef = ref => {
        this.listRef = ref;
    }
}

componentDidCatch(error, info)

如果一个组件定义了componentDidCatch生命周期,它将成为一个错误边界,错误边界会捕捉在渲染期间、在生命周期方法中和在构造函数中的错误,就像使用try catch,不会将错误直接抛出了,保证了应用的可用性。

class A extends React.Component {
    constructor() {} // 用于初始化 state
    // 用于替换'componentWillReceiveProps',该函数会在初始化和'update'时被调用
    // 因为该函数是静态方法,所以在外部无法取得'this'
    // 如果需要对比'prevProps',需要单独在'state'中维护
    static getDerivedStateFromProps(nextProps,prevState){}
    // 判断是否需要更新组件,多用于组件的性能优化
    shouldComponentUpdate(nextProps,nextState) {}
    // 组件挂载后调用,可以在该函数中进行请求或订阅
    componentDidMount() {}
    // 用于获取最新的DOM数据
    getSnapshotBeforeUpdate() {}
    // 组件即将销毁,可以此处移除事件绑定,定时器或销毁数据
    componentWillUnMount() {}
    // 组件销毁后调用
    componentDidUnMount() {}
    // 组件更新后调用
    componentDidUpdate() {}
    // 渲染组件
    render()
}