[深入React] 7.组件生命周期

React生命周期

生命周期一共分三段:初始化,运行中,销毁。按照顺序:

初始化

getDefaultProps():Object

全局只会调用一次,为当前类生成的默认props,会被父组件传入的同名props覆盖。

getInitialState():Object

为当前组件生成最初的state,此时可以访问this.props

componentWillMount

mount直译为挂载,就是组件在页面中有对应的DOM。

render

严格意义上render不是一个生命周期环节,它只是一个生成虚拟DOM的方法。需要返回一个虚拟DOM树或者null

componentDidMount

组件已经被挂载DOM,生成了this.refs,也是初始化中唯一可以发ajax的环节。

整个初始化阶段结束。

运行中

运行中就是组件(挂载)在页面上的阶段。当组件自己setState或者父辈容器setState之后会触发一次update

componentWillReceiveProps(newProps):void

  • 父组件update后会render出一个本组件的新虚拟DOM
  • React将新虚拟DOM的props,赋值给本组件的this.props
  • 在赋值之前先调用本方法,参数是新的props

主要用于更新由props派生的state,这种情况下本环节就 很重要 ,比如以userId为参数的头像组件:

var Avatar = React.createClass({
    getInitialState:function(){
        return {
            avatar_url:''
        };
    },
    componentDidMount:function(){
        var self = this;
        this.avatarAjax = $.get('/get_avatar/',{
            id:this.props.id
        },function(url){
            self.avatarAjax = null;
            this.setState({
                avatar_url:url
            });
        });
    },
    componentWillReceiveProps:function(newProps){
        if(newProps.id!==this.props.id){
            if(this.avatarAjax){
                this.avatarAjax.abort();
            }
            this.avatarAjax = $.get('/get_avatar/',{
                id:this.props.id
            },function(url){
                self.avatarAjax = null;
                this.setState({
                    avatar_url:url
                });
            });
        }
    },
    render:function(){
        return _('image',{
            src:this.state.avatar_url
        },null);
    }
});

优化:

var Avatar = React.createClass({
    getInitialState:function(){
        return {
            avatar_url:''
        };
    },
    componentDidMount:function(){
        this.update(this.props);
    },
    componentWillReceiveProps:function(newProps){
        if(newProps.id!==this.props.id){
            this.update(newProps);
        }
    },
    render:function(){
        return _('image',{
            src:this.state.avatar_url
        },null);
    },
    update:function(props){
        var self = this;
        $.get('/get_avatar/',{
            id:props.id
        },function(url){
            self.avatarAjax = null;
            this.setState({
                avatar_url:url
            });
        });
    },
});

shouldComponentUpdate():bool

主要用于性能优化,初期可以不必理会。用于告诉React对于本次update,本组件不需要重新update

componentWillUpdate

render

componentDidUpdate

一次更新结束。

销毁阶段

componentWillUnmount

销毁只有这一个环节,组件unmount后就销毁了,将不再重新mount到其他DOM上。

var i = 0;
var content = document.getElementById('content');
var Item = React.createClass({
    getInitialState:function(){
        // 赋予对象 id
        if(!this.itemId){
            this.itemId = ++i;
        }
        console.log('initState: '+ this.itemId);
        return {};
    },
    componentWillReceiveProps:function(newProps){
        if(this.props.id!==newProps.id)
            console.log(this.props.id,newProps.id);
    },
    render:function(){
        return _('div',null,this.props.id);
    },
    componentWillUnmount:function(){
        console.log('unmount: '+this.itemId);
    }
});

var List = React.createClass({
    componentWillUnmount:function(){
        console.log('list unmount');
    },
    render:function(){
        return _('div',null,
            this.props.data.map(function(id,i){
                return _(Item,{
                    key:i,
                    id:id
                });
            }
        ));
    }
});

ReactDOM.render(_(List,{data:[1,2,3]}),content);
setTimeout(function() {
    ReactDOM.render(_(List,{data:[1,2]}),content);
    setTimeout(function() {
        ReactDOM.render(_(List,{data:[1,2,3]}),content);
    }, 10);
}, 10);
/* 输出为
initState: 1
initState: 2
initState: 3
unmount: 3
initState: 4
 */

这个阶段主要用来解绑已经绑定的事件,取消发出的异步请求(timeout,ajax等)。防止setState被再次调用,并释放内存。

头像组件示例:

var Avatar = React.createClass({
    getInitialState:function(){
        return {
            avatar_url:''
        };
    },
    componentDidMount:function(){
        this.update(this.props);
    },
    componentWillReceiveProps:function(newProps){
        if(newProps.id!==this.props.id){
            this.update(newProps);
        }
    },
    render:function(){
        return _('image',{
            src:this.state.avatar_url
        },null);
    },
    componentWillUnmount:function(){
        if(self.avatarAjax){
            self.avatarAjax.abort();
            self.avatarAjax = null;
        }
    },
    update:function(props){
        var self = this;
        if(this.avatarAjax){
            this.avatarAjax.abort();
        }
        this.avatarAjax = $.get('/get_avatar/',{
            id:props.id
        },function(url){
            self.avatarAjax = null;
            this.setState({
                avatar_url:url
            });
        });
    },
});
posted @ 2016-11-09 17:19  p2world  阅读(214)  评论(0编辑  收藏  举报