频道栏目
首页 > 资讯 > 其他 > 正文

(十二)React-Native-生命周期详解

16-11-07        来源:[db:作者]  
收藏   我要投稿

一.React-Native生命周期

说到生命周期,大家大概也能想到就是创建、销毁、状态改变。RN的组件就是一个状态机。它接收两个输入参数:props和state,返回一个Virtual DOM。和Native一样,RN也为我们提供相应的钩子函数。RN的状态变化取决于props和state。我们先来看一张经典图。


这张图涵盖了一个组件从创建、运行到销毁的整个过程。大家可以看到,初始化的时候会调用5个函数(按先后顺序)。这5个函数在整个组件被创建到销毁的过程中只调用一次。初始化完毕后,当组件的props或者state改变都会触发不同的钩子函数,继而引发组件的重新渲染。现在我们把这过程拆开一点一点来分析。

初始化

我们先来看初始化,在初始化的过程中,会按顺序调用下面5个函数。

getDefaultProps:组件实例创建前调用,多个实例间共享引用。注意:如果父组件传递过来的Props和你在该函数中定义的Props的key一样,将会被覆盖。

getInitalState:组件示例创建的时候调用的第一个函数。主要用于初始化state。注意:为了在使用中不出现空值,建议初始化state的时候尽可能给每一个可能用到的值都赋一个初始值。

componentWillMount:在render前,getInitalState之后调用。仅调用一次,可以用于改变state操作。

render:组件渲染函数,会返回一个Virtual DOM,只允许返回一个最外层容器组件。render函数尽量保持纯净,只渲染组件,不修改状态,不执行副操作(比如计时器)。

componentDidMount:在render渲染之后,React会根据Virtual DOM来生成真实DOM,生成完毕后会调用该函数。在浏览器端(React),我们可以通过this.getDOMNode()来拿到相应的DOM节点。然而我们在RN中并用不到,在RN中主要在该函数中执行网络请求,定时器开启等相关操作

下面我们来演示getDefaultProps初始化Props以及父组件覆盖问题(AppConnect和Provider是和redux相关的代码,大家请跳过这一行):


比如我们在这里定义了SimpleApp的默认Props为一个key为name,value为wsd的字典(ES6以后废除了getDefaultProps而使用上述方式),然后我们在它的父组件App中传入一个同样key为name的Props,然后我们在SimpleApp中使用this.props.name把props打印出来,如下:


可以看到,原先的wsd被后面传入的kingStart覆盖了。

然后我们来看初始化State的演示(ES6里使用constructor):


我们初始化一个state为key为sex,value为boy的state对象,然后我们在componentWillMount函数中改变已经初始化的sex和没有声明的age,最后在render中打印:


可以看到我们在render中打印出了state中两个属性的值。在这里我们需要注意的是,如果在componentWillMount中直接修改state的值不会引发render的再次渲染。而如果把修改state的操作放到在render执行完之后的componentDidMount中,是会引发render的再次渲染的。

运行中

初始化完成之后,组件将会进入到运行中状态,运行中状态我们将会遇到如下几个函数:

 

componentWillReceiveProps(nextProps):props改变(父容器来更改或是redux),将会调用该函数。新的props将会作为参数传递进来,老的props可以根据this.props来获取。我们可以在该函数中对state作一些处理。注意:在该函数中更新state不会引起二次渲染。

boolean shouldComponentUpdate(object nextProps, object nextState):该函数传递过来两个参数,新的state和新的props。state和props的改变都会调到该函数。该函数主要对传递过来的nextProps和nextState作判断。如果返回true则重新渲染,如果返回false则不重新渲染。在某些特定条件下,我们可以根据传递过来的props和state来选择更新或者不更新,从而提高效率。

componentWillUpdate(object nextProps, object nextState):与componentWillMount方法类似,组件上会接收到新的props或者state渲染之前,调用该方法。但是不可以在该方法中更新state和props。

render:跟初始化的时候功能一样。

componentDidUpdate(object prevProps,object prevState):和初始化时期的componentDidMount类似,在render之后,真实DOM生成之后调用该函数。传递过来的是当前的props和state。在该函数中同样可以使用this.getDOMNode()来拿到相应的DOM节点。如果你需要在运行中执行某些副操作,请在该函数中完成。

 

我们来演示componentWillReceiveProps的调用时机,对于顶层组件,我们添加一个文本及一个点击事件:


按钮点击以后,我们将自身state的name属性改变,并传递给SimpleApp(这里的AppConnect就是SimpleApp),结果如下:


我们可以看到,第一次render,打印的是defaultProps传过来的props。当按钮点击,顶层组件state改变,引发顶层组件重新渲染,父组件传递的name发生改变,componentWillReceiveProps被调用,继而引发二次渲染。在第二次render的时候,打印出来的就是新传递过来的props。

销毁

销毁阶段只有一个函数,很简单

componentWillUnmount:组件DOM中移除的时候调用。在这里进行一些相关的销毁操作,比如定时器,监听等等。

为了加深记忆,我们把初始化和运行中所有的钩子函数写出来,让大家看看最终的运行结果。


我们首先初始化组件,不执行任何操作,打印结果如图所示:


当我们点击按钮,改变组件的props之后,打印结果如下:


我们给自身组件添加了一个点击事件,点击之后改变自身的state,如下:


点击之后,再来看调用结果:


二.props和state

 

上面讲完了生命周期,我们对props和state的不同点以及相同点作一个总结,加深大家理解。

相同点

1.不管是props还是state的改变,都会引发render的重新渲染。

2.都能由自身组件的相应初始化函数设定初始值。

不同点

1.初始值来源:state的初始值来自于自身的getInitalState(constructor)函数;props来自于父组件或者自身getDefaultProps(若key相同前者可覆盖后者)。

2.修改方式:state只能在自身组件中setState,不能由父组件修改;props只能由父组件修改,不能在自身组件修改。

3.对子组件:props是一个父组件传递给子组件的数据流,这个数据流可以一直传递到子孙组件;state代表的是一个组件内部自身的状态,只能在自身组件中存在。



 

'use strict'
import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    PixelRatio,
    AlertIOS,
    ActionSheetIOS,
    WebView,
} from 'react-native';
var  Dimensions = require('Dimensions');
var width = Dimensions.get('window').width;
var height = Dimensions.get('window').height;


class ReactiveOne  extends Component{
    constructor(props){
      super(props);
        console.log('constructor');
        this.state = {
            sex:'box',
        };
    }
    componentWillMount() {
        this.setState({
            age: '16',
        });
        console.log('componentWillMount');
    }
    componentDidMount() {
        console.log('componentDidMount');
        this.setState({
            sex:'girls',
            age:'20',
        });
    }
    render () {
        console.log('render');
        return (
            'red',width:width,height:height
        }}>
        );
    }
    componentWillReceiveProps (nextProps) {

        console.log('conponentWillReceiveProps',nextProps);
    }
    shouldComponentUpdate() {
        console.log('shouldComponentUpdate');
        return true;
    }
    componentWillUpdate() {
        console.log('componentWillUpdate');
    }
    componentDidUpdate () {
        console.log('componentDidUpdate');
    }
}
AppRegistry.registerComponent('ReactiveOne', ()=>ReactiveOne);

 

 

2016-11-04 14:01:38.120 [info][tid:com.facebook.react.JavaScript] constructor

2016-11-04 14:01:38.120 [info][tid:com.facebook.react.JavaScript] componentWillMount

2016-11-04 14:01:38.120 [info][tid:com.facebook.react.JavaScript] render

2016-11-04 14:01:38.124 [info][tid:com.facebook.react.JavaScript] componentDidMount

2016-11-04 14:01:38.125 [info][tid:com.facebook.react.JavaScript] shouldComponentUpdate

2016-11-04 14:01:38.125 [info][tid:com.facebook.react.JavaScript] componentWillUpdate

2016-11-04 14:01:38.126 [info][tid:com.facebook.react.JavaScript] render

2016-11-04 14:01:38.131 [info][tid:com.facebook.react.JavaScript] componentDidUpdate

这里特别注意:shouldComponentUpdate 函数的返回值是一个bool的 true 表示允许允许应用进行属性值的修改,执行后续的操作,false 表示不允许执行后续的操作

如果不实现shouldComponentUpdate 该方法,则走系统的默认的去返回true或者false ;

如果用户实现了shouldComponentUpdate 该方法,则应用走用户的结果 如果无返回值则报下面的错误:

2016-11-04 14:01:00.221 [warn][tid:com.facebook.react.JavaScript] Warning: ReactiveOne.shouldComponentUpdate(): Returned undefined instead of a boolean value. Make sure to return true or false.

相关TAG标签
上一篇:Kotlin——1.实际使用,安利与相关配置
下一篇:Android的四大组件
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站