美文网首页
React组建的生命周期

React组建的生命周期

作者: Android_冯星 | 来源:发表于2018-08-09 18:26 被阅读0次

    React 生命周期

    image.png

    React生命周期主要包括4个阶段:

    1. 初始化阶段
    2. 实例化阶段
    3. 更新阶段
    4. 销毁阶段

    1 设置组件的默认属性 getDefaultProps

    对于每个组件实例来讲,这个方法只会调用一次,该组件类的所有后续应用,getDefaultPops 将不会再被调用,其返回的对象可以用于设置默认的 props(properties的缩写) 值。

     getDefaultProps: function(){
            return {
                name: 'pomy',
                git: 'dwqs'
            }
        },
    

    -### 2 设置组件的初始化状态 getInitialState

    对于组件的每个实例来说,这个方法的调用有且只有一次,用来初始化每个实例的 state,在这个方法里,可以访问组件的 props。每一个React组件都有自己的 state,其与 props 的区别在于 state只存在组件的内部,props 在所有实例中共享。

    其返回值可以赋值给组件的this.state属性

    getInitialState 和 getDefaultPops 的调用是有区别的,getDefaultPops 是对于组件类来说只调用一次,后续该类的应用都不会被调用,而 getInitialState 是对于每个组件实例来讲都会调用,并且只调一次。

    var LikeButton = React.createClass({
      getInitialState: function() {
        return {liked: false};
      },
      handleClick: function(event) {
        this.setState({liked: !this.state.liked});
      },
      render: function() {
        var text = this.state.liked ? 'like' : 'haven\'t liked';
        return (
          <p onClick={this.handleClick}>
            You {text} this. Click to toggle.
          </p>
        );
      }
    });
    
    ReactDOM.render(
      <LikeButton />,
      document.getElementById('example')
    );
    

    每次修改 state,都会重新渲染组件,实例化后通过 state 更新组件,会依次调用下列方法:

    1、shouldComponentUpdate
    2、componentWillUpdate
    3、render
    4、componentDidUpdate

    但是不要直接修改 this.state,要通过 this.setState 方法来修改。

    getDefaultProps相当于ES6中static defaultProps = {}
    getInitialState相当于constructor中的 this.state = {}

    3 componentWillMount() 组件挂载之前

    在render方法之前调用,主要做一些业务逻辑的处理。如,对state状态的操作;进行开启定时器、向服务器发送请求等操作

    在组件挂载之前调用且全局只调用一次。如果在这个钩子里可以setState,render后可以看到更新后的state,不会触发重复渲染。该生命周期可以发起异步请求,并setState。(React v16.3后废弃该生命周期,可以在constructor中完成设置state

    该方法在首次渲染之前调用,也是再 render 方法调用之前修改 state 的最后一次机会。

    4 render()

    组件渲染 根据state值,渲染并返回虚拟的DOM

    render是一个React组件必须定义的生命周期,用来渲染dom。⚠️不要在render里面修改state,会触发死循环导致栈溢出。render必须返回reactDom

    render() {
        const {nodeResultData: {res} = {}} = this.props;
        if (isEmpty(res)) return noDataInfo;
        const nodeResult = this.getNodeResult(res);
        return (
            <div className="workspace-dialog-result">
                {nodeResult}
            </div>
        );
    

    该方法具有特殊的规则:

    • 只能通过this.props和this.state访问数据
    • 可以返回null、false或任何React组件
    • 只能出现一个顶级组件(不能返回数组)
    • 不能改变组件的状态
    • 不能修改DOM的输出

    render方法返回的结果并不是真正的DOM元素,而是一个虚拟的表现,类似于一个DOM tree的结构的对象。react之所以效率高,就是这个原因。

    5 componentDidMount() 组件挂载完成后

    组件已经被渲染到页面中后触发:此时页面中有了真正的DOM的元素,可以进行DOM相关的操作

    在组件挂载完成后调用,且全局只调用一次。可以在这里使用refs,获取真实dom元素。该钩子内也可以发起异步请求,并在异步请求中可以进行setState。

    componentDidMount() {
        axios.get('/auth/getTemplate').then(res => {
            const {TemplateList = []} = res;
            this.setState({TemplateList});
        });
    }
    

    挂载成功函数。该函数不会再render函数调用完成之后立即调用,因为render函数仅仅是返回了JSX的对象,并没有立即挂载到DOM树上,而componentDidMount是在组件被渲染到DOM树之后被调用的。另外,componentDidMount函数在进行服务器端渲染时不会被调用。

    更新阶段

    6 componentWillReceiveProps (nextProps ) props即将变化之前

    props发生变化以及父组件重新渲染时都会触发该生命周期,在该钩子内可以通过参数nextProps获取变化后的props参数,通过this.props访问之前的props。该生命周期内可以进行setState。(React v16.3后废弃该生命周期,可以用新的周期 static getDerivedStateFromProps 代替)

        componentWillReceiveProps: function(nextProps) {
            if (nextProps.bool) {
                this.setState({
                    bool: true
                });
            }
        }
    

    7 shouldComponentUpdate() 是否重新渲染

    组件挂载之后,每次调用setState后都会调用shouldComponentUpdate判断是否需要重新渲染组件。默认返回true,需要重新render。返回fals则不会执行 render 以及后面的 componentWillUpdate,componentDidUpdate 方法。在比较复杂的应用里,有一些数据的改变并不影响界面展示,可以在这里做判断,优化渲染效率。

    
    shouldComponentUpdate(newProps, newState) {
        if (newProps.number < 5) return true;
        return false
    }
    //该钩子函数可以接收到两个参数,新的属性和状态,返回true/false来控制组件是否需要更新。
    

    一般我们通过该函数来优化性能:

    一个React项目需要更新一个小组件时,很可能需要父组件更新自己的状态。而一个父组件的重新更新会造成它旗下所有的子组件重新执行render()方法,形成新的虚拟DOM,再用diff算法对新旧虚拟DOM进行结构和属性的比较,决定组件是否需要重新渲染

    无疑这样的操作会造成很多的性能浪费,所以我们开发者可以根据项目的业务逻辑,在shouldComponentUpdate()中加入条件判断,从而优化性能

    例如React中的就提供了一个PureComponent的类,当我们的组件继承于它时,组件更新时就会默认先比较新旧属性和状态,从而决定组件是否更新。值得注意的是,PureComponent进行的是浅比较,所以组件状态或属性改变时,都需要返回一个新的对象或数组

    8 componentWillUpdate() 组件将要更新

    shouldComponentUpdate返回true或者调用forceUpdate之后,componentWillUpdate会被调用。不能在该钩子中setState,会触发重复循环。(React v16.3后废弃该生命周期,可以用新的周期 getSnapshotBeforeUpdate )

    9 render开始更新

    10 componentDidUpdate()

    这个方法和 componentDidMount 类似,在组件重新被渲染之后,componentDidUpdate(object prevProps, object prevState) 会被调用。可以在这里访问并修改 DOM。

    除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。该钩子内setState有可能会触发重复渲染,需要自行判断,否则会进入死循环。

    componentDidUpdate() {
        if(condition) {
            this.setState({..}) // 设置state
        } else {
            // 不再设置state
        }
    }
    

    11 componentWillUnmount() 组件即将被卸载

    组件被销毁时触发。这里我们可以进行一些清理操作,例如清理定时器,取消Redux的订阅事件等等。

    每当React使用完一个组件,这个组件必须从 DOM 中卸载后被销毁,此时 componentWillUnmout 会被执行,完成所有的清理和销毁工作,在 componentDidMount 中添加的任务都需要再该方法中撤销,如创建的定时器或事件监听器。

    当再次装载组件时,以下方法会被依次调用:

    1、getInitialState
    2、componentWillMount
    3、render
    4、componentDidMount

    setState

    state:组件的属性,主要用来存储组件自身需要的数据,每次数据更新都是通过修改state属性的值,ReactJs内部会监听state属性的变化,一旦发生变化的,就会主动调用render方法更新虚拟dom结构。

    要修改state,只能使用this.setState(),不能使用this.state.value=2类似方式设置state,一是不会驱动重新渲染,二是很可能被后面的操作替换,造成无法预知的错误。此外,React利用状态队列来实现setState的异步更新,避免频繁地重复更新state。

    setState的调用是有风险的,在某些生命周期函数中调用可能会无用甚至早恒循环调用导致崩溃。state的初始化一般在构造函数中实现;setState可以在装载过程的componentWillMount、componentDidMount中调用;setState可以在更新过程中的componentWillReceiveProps、componentDidUpdate中调用。

    虚拟dom

    将真实的dom结构映射成一个Json数据结构。

    例子

    import React from 'react'
    import ReactDOM from 'react-dom';
    
    class SubCounter extends React.Component {
        componentWillReceiveProps() {
            console.log('9、子组件将要接收到新属性');
        }
    
        shouldComponentUpdate(newProps, newState) {
            console.log('10、子组件是否需要更新');
            if (newProps.number < 5) return true;
            return false
        }
    
        componentWillUpdate() {
            console.log('11、子组件将要更新');
        }
    
        componentDidUpdate() {
            console.log('13、子组件更新完成');
        }
    
        componentWillUnmount() {
            console.log('14、子组件将卸载');
        }
    
        render() {
            console.log('12、子组件挂载中');
            return (
                    <p>{this.props.number}</p>
            )
        }
    }
    
    class Counter extends React.Component {
        static defaultProps = {
            //1、加载默认属性
            name: 'sls',
            age:23
        };
    
        constructor() {
            super();
            //2、加载默认状态
            this.state = {number: 0}
        }
    
        componentWillMount() {
            console.log('3、父组件挂载之前');
        }
    
        componentDidMount() {
            console.log('5、父组件挂载完成');
        }
    
        shouldComponentUpdate(newProps, newState) {
            console.log('6、父组件是否需要更新');
            if (newState.number<15) return true;
            return false
        }
    
        componentWillUpdate() {
            console.log('7、父组件将要更新');
        }
    
        componentDidUpdate() {
            console.log('8、父组件更新完成');
        }
    
        handleClick = () => {
            this.setState({
                number: this.state.number + 1
            })
        };
    
        render() {
            console.log('4、render(父组件挂载)');
            return (
                <div>
                    <p>{this.state.number}</p>
                    <button onClick={this.handleClick}>+</button>
                    {this.state.number<10?<SubCounter number={this.state.number}/>:null}
                </div>
            )
        }
    }
    ReactDOM.render(<Counter/>, document.getElementById('root'));
    
    
    image.png

    相关阅读

    图解ES6中的React生命周期

    React:组件的生命周期

    React组件生命周期过程说明

    React组件生命周期

    React组件生命周期详解

    React组件生命周期详解
    1

    相关文章

      网友评论

          本文标题:React组建的生命周期

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