react 组件的生命周期

前言

  在开发模式下,你可能会发现在组件第一次初始话的时候或者时更新的时候,对应的生命周期会出现运行两次的情况,这是因为在开发模式下,react使用了<React.StrictMode>组件,你可以直接在根目录下的index.tsx中注释掉他

生命周期图鉴

  

生命周期列表

  constructor(props):

    介绍:构造函数,组件加载时最先执行的生命周期钩子函数

    执行时机:组件首次渲染时会执行

    接收参数:props 由父级传递的props

  static getDerivedStateFromProps(props,state)

    介绍:当组件的state和props改变时执行的方法

    执行时机:组件首次渲染以及组件更新时执行

    接收参数:props 组件接收到的props副本,state组件当前state副本

    返回值:必须要有返回值,且返回值必须为null 或 {}对象,返回为null的时候,视图会按照原有的props和state渲染,但返回值为{}的时候,会将其与state合并,并将最新的state作为本次视图渲染的依据

  shouldComponentUpdate(nextProps,nextState)

    介绍:组件即将更新之前执行的方法,可以通过return值决定组件是否更新渲染,但是即便组件没有更新渲染,state和props的改动还是存在,只是没有视图更新;这块可以用来做性能优化的东西

    执行时机:组件更新时执行

    接收参数:nextProps 组件接收的Props,nextState 组件当前的state

    返回值:返回一个boolean类型的值,如果是false,则组件更新到此为止,后续的渲染逻辑将不会执行

  render

    介绍:组件渲染函数,这是组件中唯一要实现的方法

    执行时机:组件首次渲染和组件更新时会触发

    接收参数:无

    返回值:返回一个元素作为渲染模板

  componentDidMount

    介绍:组件第一次挂载时执行生命周期钩子函数

    执行时机:组件首次渲染时执行

    接收参数:无

  getSnapshotBeforeUpdate(prevProps,prevState)

    介绍:组件渲染更新提交到真实dom之前生命周期钩子函数;在此处,已经可以访问更新后的ref,但是更新后的渲染结果仍未提交到真实dom,真实dom仍然是旧的。

    执行时机:组件更新时执行

    接收参数:组件此时的props和state

    返回值:在此方法内返回的任何值,都会被componentDidUodate接收

  componentDidUpdate(prevProps,prevState,snapshot)

    介绍:组件更新后生命周期钩子函数;

    执行时机:组件更新完成后执行

    接收参数:prevProps为组件props、prevState为组件state、snapshot为组件getSnapshotBeforeUpdate中return的值

  componentWillUnmount

    介绍:销毁前调用,在这个时候组件的一切功能都是可以正常使用的,但是在此调用setState,组件永远不会更新,因为在此此方法执行之后,组件将进行销毁

    执行时机:组件销毁前调用

    接收参数:无

过时的生命周期方法 这些声明周期虽然仍然有效,但是不推荐使用

UNSAFE_componentWillMount()

UNSAFE_componentWillReceiveProps()

UNSAFE_componentWillUpdate()

详细信息

constructor

  构造函数react 实例话第一步就是执行这个方法,在这里你可以定义state的初始数据。这个方法可以不定义,但是如果你定义之后,就必须在内部使用super()方法,这是es6的规范

  

render

  这个钩子函数虽然是组件的渲染方法,但并不是真正意义上的把元素渲染成dom的方法,在它之后还有一个把元素渲染成dom的步骤,这一步只是return一个元素对象,这个并不是组件的执行渲染功能的函数,

  它的返回值是一个这样的react 元素对象,react就是最终通过它去生成dom对象。它是唯一一个react.Componet 类中必须实现的方法

 

componentDidMount 

  组件渲染完成并且挂载在dom上之后调用,这个类似与vue的mounted,者意味着这一步组件中的元素都已经转话成真实的dom,我们可以在这里进行dom操作

  它可以访问this

  并且不携带参数

  e的值为undefined

  

shouldComponentUpdate

  组件即将更新时触发,这个生命周期钩子在getDerivedStateFromProps之后,在render之前调用,通过return false或者true 来决定是否更新组件。

  这个组件在提升性能方面非常有用,假设一个父组件中存在10个子组件,那么当父组件state或者props改变时,即便子组件没有变更,也会重新渲染,这样白白浪费了渲染开销,所以可以在子组件中的sholdComponentUpdate中判断state或者props是否发生改变,然后决定子组件是否重新渲染

  这个方法接受两个参数nextProps 更新后的props nextState 更新后的state

 getSnapshotBeforeUpdate

  当元素最近一次渲染输出(既是当数据更新,触发react重新渲染组件之后,在把新渲染的组件挂载在dom之前)触发,这个钩子函数你应该极少使用。

 getSnapshotBeforeUpdate(prevProps, prevState) {
        //这个方法必须要和componentDidUpdate方法一起使用
        console.log(this);//可以访问this
        // 不推荐在此处使用setState,虽然仍可以使用
        return {a: 415463564}; //在这里return的值,会传递给componentDidUpdate钩子函数的第三个参数
    }

componentDidUpdate

componentDidUpdate(prevProps, prevState, snapshot) {
        console.log(prevProps);//更新之前的props
        console.log(prevState);//更新之前的state
        console.log(snapshot);//getSnapshotBeforeUpdate生命周期中return的值
        console.log(this.state);//这里仍然可以获取this
        //值得一提的是在这里尽量不要掉用setState(),不然有可能会造成无限更新的情况发生
        //因为在这一步react已经完成更新了,所以不能像shouComponentUpdate一下修改prevProps或者是prevState来触发视图更新
    }

static getDerivedStateFromProps()

  在第一次进入,和发生更新的时候(setState,props更新或者调用forceUpdate)都会触发这个生命周期钩子,并且是在render方法之前调用。同时通过return值,我们可以改变最后的渲染结果。(return的值会直接同步至state中,比如在state中有一个index属性,它的值为1,而你在此方法内返回{index:99},那么最后渲染的值为99,但是不建议在这里直接改变state,我们应当遵循react的setState改变原则)。ps:在这里无法访问this

static getDerivedStateFromProps(props, state) {
        console.log(props, state);
        state.idx = 180; //只要在此方法内改变props 或者state中的值,那么最终的渲染结果,就以此为准。即便return 为null
        return null;
    }

一些api

setState 

  setState是发起一个更新组件的请求,而非立即更新,它不会立即改变state和立即更新组件。为了提高更新效率,react不会对每一次的改变立即更新,而是形成一个更新队列,批量更新。这样就避免了很多无用的更新。

  不要再组件更新的钩子函数中使用setState(),因为即便state没有发生任何变化,此方法也会促使视图进行更新。所以不要在会重复触发的,组件更新生命周期钩子函数中:shouldComponentUpdate、render、getSnapshotBeforeUpdate、componentWillUpdate使用此方法,有可能会造成无限次数的数据更新

componentDidMount() {
        for (let i = 0; i < 100; i++) {
            this.setState({idx: i++});
        } //最终只会触发一次componentDidUpdate
     console.log(this.state.idx) //打印结果为state在constructor 定义初始值 1
}

  setState可接收不同的参数 

  1.接收一个回调函数

 this.setState((state, props) => {
            //state和props 参数是目前组件的的最新的state,props。但是它仍不是此回调函数 return之后的state值
            
            return {idx: '12345'} //return的值会与state进行浅合并,只有在return语句执行之后,组件的state才会进行更新
        })

  2.接收一个对象和一个回调函数,如果你想立即获取改变后的state值,可以使用这个方法

 //通过第一个参数对象修改state,第二个回调函数参数会在componentDidUpdate之后执行
        this.setState({idx: e}, function () {
            console.log(this.state);
        })

forceUpdate 强制组件重新更新

 this.state.idx=999;
        //强制组件重新渲染,回调函数将在componentDidUpdate之后执行
        this.forceUpdate(function () {
            console.log('强制执行')//
        })

 

结合react的生命周期图示,你可能会更清晰

posted @ 2020-05-22 12:59  眼里有激光  阅读(621)  评论(0编辑  收藏  举报