欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

附实例!图解React的生命周期及执行顺序

程序员文章站 2022-11-22 08:11:35
本文由云+社区发表 作者:前端林子 1.七个可选的生命周期 可以结合下图来看: (1) componentWillMount() 仅在render()方法前被调用一次,如果在该方法中调用了setState方法去改变组件的状态值,那么调用render()后,将会直接看到改变过了的状态值,并且不论状态值 ......

本文由云+社区发表

作者:前端林子

1.七个可选的生命周期

可以结合下图来看:

附实例!图解React的生命周期及执行顺序

(1) componentwillmount() 仅在render()方法前被调用一次,如果在该方法中调用了setstate方法去改变组件的状态值,那么调用render()后,将会直接看到改变过了的状态值,并且不论状态值怎么改变,componentwillmount()都不会再被调用。

(2) componentdidmount() 仅在render()方法后被立即调用一次(客户端),相对于父组件而言,该方法在子组件中会先被调用。如果需要使用一些javescript框架或者类似于setinterval()这样的方法,建议在该方法内使用。

(3) shouldcomponentupdate(object nextprops, object nextstate) 在初始渲染调用render()方法时不会被调用,后面在接受到新的state或者props时,在render()方法前被调用。为防止一些潜在的bug,该方法默认总是返回true。如果你确定state及props改变后不需要渲染组件,那么也可以指定返回false,需要注意的是,这样的结果会导致后面的render()、componentwillupdate()、componentdidupdate()都不会被调用。

一般的,我们可以通过该函数来优化性能:

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

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

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

(4) componentwillreceiveprops(object nextprops) 在初始渲染调用render()方法时不会被调用,当接收到一个新的props时,该方法被调用。我们都知道,如果改变一个状态的值,则会触发render()方法,所以可以在这个方法里调用setstate()方法去改变一个状态的值,当该方法接收到新的props时,setstate()就可以避免一次额外的render()了。 在这个方法里,尤其需要注意一点,就是接收到新的props一定会触发render()方法,但是render()方法被触发不一定是因为接收到了新的props

(5) componentwillupdate(object nextprops, object nextstate) 在初始渲染调用render()方法时不会被调用,当接收到新的props及state时,在render()方法之前被调用。

不要在此方法再去更新props 或者 state

(6) componentdidupdate(object prevprops, object prevstate) 在初始渲染调用render()方法时不会被调用,当组件更新被刷新到dom之后被立即调用。

可以在这里访问,并修改 dom

(7) componentwillunmount() 在组件从dom上卸载前被调用,在这个方法里面,我们主要是完成一些清除操作,比如说清除掉一些过时了的定时器等。

2.执行顺序及次数

(1) getdefaultprops(),调用1次

(2) getinitialstate(),调用1次

(3) componentwillmount(),调用1次

(4) render(),调用>=1次

(5) componentdidmount():仅客户端,调用1次

(6) componentwillreceiveprops(object nextprops),调用>=0次

(7) shouldcomponentupdate(object nextprops, object nextstate),调用>=0次

(8) componentwillupdate(object nextprops, object nextstate),调用>=0次

(9) render(),调用>=1次

(10) componentdidupdate(object prevprops, object prevstate),调用>=0次

(11) componentwillunmount(),调用1次

3.实例

我写了一个小demo可直接在浏览器里运行,大家可以通过控制台查看父组件、子组件中的各生命周期调用的顺序:

<!doctype html>

<html>

    <head>

        <script src="https://fb.me/react-15.2.0.js"></script>

        <script src="https://fb.me/react-dom-15.2.0.js"></script>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>

    </head>

<body>

    <div id="app-container"></div>

    <script type="text/babel">
        var subcounter = react.createclass({
            componentwillreceiveprops:function() {
                console.log('9、子组件将要接收到新属性');
            },

            shouldcomponentupdate:function(newprops, newstate) {
                console.log('10、子组件是否需要更新');
                if (newprops.number < 5) return true;
                return false
            },

            componentwillupdate:function() {
                console.log('11、子组件将要更新');
            },

            componentdidupdate:function() {
                console.log('13、子组件更新完成');
            },

            componentwillunmount:function() {
                console.log('14、子组件将卸载');
            },

            render:function() {
                console.log('12、子组件挂载中');
                return (
                        <p>{this.props.number}</p>
                )
            }
        });

        var counter = react.createclass({
           
            getinitialstate:function(){
                return(
                    this.state={
                        number:0
                    }
                )
            },

            componentwillmount:function(){
                console.log('3、父组件挂载之前');
            },

            componentdidmount:function(){
                console.log('5、父组件挂载完成');
            },

            shouldcomponentupdate:function(newprops, newstate) {
                console.log('6、父组件是否需要更新');
                if (newstate.number<15) return true;
                return false
            },

            componentwillupdate:function() {
                console.log('7、父组件将要更新');
            },

            componentdidupdate:function() {
                console.log('8、父组件更新完成');
            },

            handleclick : function(){
                this.setstate({
                    number: this.state.number + 1
                })
            },
            render:function() {
                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('app-container'));

    </script>

</body>

</html>

点击一次按钮,通过控制台可以看到:

附实例!图解React的生命周期及执行顺序

4.小结

本文主要是图文结合地介绍了react的生命周期及执行顺序,同时附上了一个实例,可以清楚地看到父组件、子组件的调用顺序。如存在问题,欢迎指正~~~

此文已由腾讯云+社区在各渠道发布

获取更多新鲜技术干货,可以关注我们