美文网首页
React生命周期

React生命周期

作者: 初入前端的小菜鸟 | 来源:发表于2019-06-20 10:37 被阅读0次

    react 生命周期

    生命周期图

    生命周期经历三个过程

    • 装载过程(mount), 也就是把组件第一次在DOM树中渲染的过程
    • 更新过程(updata), 当组件被重新渲染的过程
    • 卸载过程(Unmount), 组件充DOM中删除的过程

    三种不同的过程,React库会一次调用组件的一些成员函数,即生命周期钩子

    装载过程中的生命周期钩子

    constructor
    getinitialState
    getDefaultProps
    componentWillMount
    render
    componentDidMount
    

    getinitialState、getDefaultPropsReact.createClass创建组件时用到的生命周期函数,在高版本的React中已经放弃这种方法,所以这次就不进行展示;

    constructor

    在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。

    Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。

    阮一峰---js类

    阮一峰---ES6 > Class

    constructor ES6中每个类的构造函数,并不是每个组件都需要定义自己的构造函数,无状态的React组件往往不需要定义构造函数,一个React组件需要构造函数,往往是为了下面的目的

    • 初始化state,因为组件生命周期中任何函数都可以访问state,那么整个生命周期中第一个被调用构造函数自然是初始化state最理想的地方
    • 绑定成员函数的this

    在ES6语法下,类的每个成员函数在执行时this应不是和类实例自动绑定的,而是在构造函数中,this就是当前组件实例,所以为了方便将来的调用,往往在构造函数中将这个实例的特定函数绑定this为当前实例

        this.count = this.count.bind(this)
    

    render

    render 函数无疑是React组件中最重要的函数,一个React组件可以忽略其他所有函数都不实现,但是一定要实现render函数,因为React组件的父类React.Component类对除了render之外的生命周期都有默认实现

    render 函数并不做实际的渲染动作,它返回一个JSX的描述的结构,最容由React来操作渲染过程

    某些特殊组件的作用不是渲染洁面,或者,组件在某些情况下没有什么内容取进行更新,那么让render函数返回一个null或者false,等于告诉React,这次组件不需要渲染任何DOM元素

    注意: render 函数应是一个纯函数,完全根据this.statethis.props 来决定返回的结果,而且不要产生任何副作用。在render函数中取调用this.setState毫无疑问是错误的,因为一个纯函数不应该引起状态的改变

    componentWillMoun和componentDidMount

    在装载过程中,componentWillMount会在调用render函数前被调用,componentDidMount则会在调用render函数后被调用,正好分别来做render前后必备的工作;

    componentWillMount 放生在"将要装载"的时候;这个时候没有任何渲染出来的结果,即使调用this.setState修改状态也不会引发重新绘制,因为一切都晚了,在这个时候可以做的事情都可以放到constructor中,可以认为这个函数存在的主要目的是和componentDidMount对称;

    componentDidMount 调用在render函数被调用完之后,componentDidMount被调用的时候,render函数返回的东西已经引发了渲染,组件已经被"装载"到DOM树上;值得注意的时,render函数被调用后,componentDidMount函数并不是马上被渲染;

    代码如下:
    import React, { Component } from 'react';
    import Counter from './Counter';  
    // app.js
    class App extends React.Component {
      render() {
        console.log('enter ControlPanel render')
        return (
          <div className="App" >
            <div style={{border: '1px solid', textAlign: 'center'}}>
            <Counter caption="First" initValue={0}/>
            <Counter caption="Second" initValue={10} />
            <Counter caption="Third" initValue={20} />
            </div>
          </div>
        )
      }
    }
    // Counter.js
    import React, { Component } from 'react';
    class Counter extends Component {
      constructor(props) {
        super(props);
        this.state = {
          count: this.props.initValue,
          name: this.props.caption
        }
      }
      componentWillMount () {
        console.log('render 运行前': this.state.name)
      }
      componentDidMount () {
        console.log('render 运行后': this.state.count)
      }
      render () {
        retrun (
          <div>{this.state.name}: {this.state.count}<div>
        )
      }
    }
    

    结果:

    componentDidMount 并不会直接运行
    可以清除的看到,componentDidMount是当三个组件都调用完成后,才一起被调用;
    因为render函数本身并不往DOM树上渲染或者装载内容,它返回的是一个JSX表示的对象,然后由React库根据返回对象决定如何渲染,而React库把所有组件返回的结果综合起来,才知道如何产生对应的DOM修改,所以React库调用Counter三个组件的render函数后,才有可能完成状态,这个时候才会依次调用组件的componentDIdMount函数;

    更新过程

    componentWillReceiveProps
    shouldComponentUpdate
    componentWillUpdate
    render
    componentDidUpdate
    

    componentWillReceiveProps

    只要父组件的render函数被调用,在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的props有没有改变,都会触发子组件的componentWillReceiveProps函数。

    // 代码 接上部分代码
    // app.js
    <button onClick={() => this.forceUpdate()}>aaaa</button>
    // Counter.js
     componentWillReceiveProps (nextProps) {
        console.log('enter componentReceiveProps' + this.props.name)
     }
    
    父组件render被调用

    shouldComponentUpdate(nextProps, nextState)

    除了render函数外,shouldCompoentUpdate可能是整个组件生命周期中最重要的一个函数了;

    shouldCompoentUpdate函数决定了一个组件什么时候不需要进行渲染;

    shouldCompoentUpdaterender是React生命周期函数中唯二两个要求有返回结果的函数,render返回结果将用于构造DOM对象,而shouldCompoentUpdate函数返回一个布尔值,告诉React库这个组件在本次更新中国呢是否继续;

    在React库首先调用shouldCompoentUpdate 函数,如果返回true则仅需更新,调用render,如果返回false则停止更新过程,也不会引发后续渲染。

    // 代码接上面
    // Counter.js
    shouldComponentUpdate(nextProps, nextState) {
            return (nextProps.count !== this.props.count) || (nextState.count !== this.state.count)
    }
    componentWillUpdate () {
        console.log('componentWillUpdate')
    }
    componentDidUpdate () {
        console.log('componentDidUpdate')
    }
    

    当点击aaaa进行刷新时,不会调用shouldComponentUpdate,同时也不会进行componentWillUpdate函数等的调用,当进行加减操作石,则触发;

    componentWillUpdate和componentDidUpdate

    componentWillUpdate 组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state

    componentDidUpdate 组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。

    卸载过程

    componentWillUnmount
    

    防止内存泄漏
    用法官方实例

    相关文章

      网友评论

          本文标题:React生命周期

          本文链接:https://www.haomeiwen.com/subject/goorqctx.html