RN生命周期-陪你到繁花落尽

有些事情,由天注定,从出生开始,到死亡结束。一个转身就是沧海桑田。 有些代码,由你书写,从出生开始,到死亡结束。一次擦肩就是bug满天飞~

ok,你以为我还是那个文艺女青年?书写一篇似黛玉妹妹的“花谢花飞花满天”?才不是呢。至少人家也是一名立志走向全栈的程序媛嘛,如何能脱离屌丝程序员大家庭的怀抱。所以……直接上代码。 好吧,在上代码之前要先解释清楚两个概念。 state和props。 props是一个属性,代表属性的意思。可以从外界传入,也可以由自身给出。而且一经指定,在被指定的组件的生命周期中则不再改变。 也就是说它是只读的。

//本类定义属性的写法 要加上static
static defaultProps = {
  name:'小红'
}

可以使用propTypes对属性进行检查。PropTypes是React的子类,使用它必须要将它导入。

 import  React, {Component,PropTypes} from 'react';
static propTypes = {
  name:PropTypes.string, //表示name属性必须是string类型的
}

如果要求某个属性是必须传递的,则要在后面加上isRequired。

static propTypes = {
  sex:PropTypes.string.isRequired, //设置了isRequired则这个属性的值必须从外界传递进来。
}

这里再介绍一个es6的知识点。延展操作符。当你有很多属性的时候,可以用一个延展操作符将这些属性都括起来。带到使用的时候,只需要打三个点取出。

var params = {name:'嘻嘻',age:18,sex:'男'}
//PropsTest是上一个界面
<PropsTest
  {...params}
/>

当然,我们也可以只取出延展操作符的部分属性。我们称之为结构赋值。

var params = {name:'嘻嘻',age:18,sex:'男'}
var {name,sex} = params;  //取出部分属性
<PropsTest
  name = {name}  //将属性值传出去
 sex = {sex}
/>

再来看state,它代表状态的意思。对于需要改变的数据,我们需要使用state。当然它只能是在内部赋值,而不能接受从外界传入的值。在这里每个组件都有一个系统的setState方法用来改变状态,并且它是会刷新界面的哟~那么它在刷新界面的时候其实调用的就是Render函数。在这里跟大家先声明一下,因为render函数是一个异步函数,所以在render函数里面用setState去设置值,它是不会立即刷新的。 它可以保证同时刷新多个setState方法。

export default class Test extends Component {
      state = {           //创建state有两种方式
            title:'默认值'  
}
render (
    <View style={styles.container}>
          <Text>{this.state.title}</Text>
   </View>
);
}

为了更清楚的阐述这个状态机,这里准备了一个小的案例。 写一个文本框和一个文字组件。当文本框内容发生变化的时候,触发一个回调函数,然后在回调函数中取出文本框的text值然后赋给下面的Text组件。 首先要使用文本框就要导入TextInput组件。

import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    TextInput,  //导入文本框

} from 'react-native';

写一个构造函数。其实每一个组件都可以有一个构造函数。它的第一条语句是固定的。当组件被初始化时,该函数将会被执行。通常在这个函数声明需要用的状态机变量。现在要做的就是在这里输入文字。

//构造函数
    constructor(props){
        super(props);
        //    初始状态
        this.state = {textInputValue:'请输入文字'};
    }

当开发者需要改变状态机变量的值时,一定要使用this.setState函数。 我们通过提供一个方法,用来设置新值。

//用来设置新值
    updateTextInputValue(newText) {
        //this.setState将状态机设置成一个新的值
        this.setState({textInputValue:newText});
    }
 render() {
        return (
            <View style={styles.container}>
                <TextInput style={styles.textInputStyle}
                           placeholder={'请输入文字'}
                           onChangeText={(newText)=>this.updateTextInputValue(newText)}

                >

                </TextInput>
                <Text style={styles.textShow}>
                    {this.state.textInputValue}
                </Text>
            </View>
        );
    }
}

上面代码中的调用的方法可以简写成onChangeText = {this.updateTextInputValue}。这种写法我们没办法看到newText的传递过程,但是它还是被传递了的。

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    //设置文本框的样式
    textInputStyle: {
        width:300,
        height:150,
        borderWidth:1,
        borderStyle:'dashed',
        margin:10
    },
    textShow: {
        width:200,
        height:30,
        backgroundColor:'blue',
    }
});

状态机变量value的默认值为:’请在这里输入文字’,当我们修改textarea里面的值时,就会触发updateText函数(PS:给onChangeText赋值时最好用箭头函数,不要写成onChangeText={this.handleChange}),在handleChange函数里面改通过this.state将textarea里面的值赋给状态机变量value。当状态机变量的值发生变化时,就会重新调用render函数进行UI渲染。状态机变量的值只要发生变化就会调用render函数重新渲染一次。 用一句话来总结一下呢,就是props比较专情,一经指定呢是不会发生改变的,但是state呢却是比较博爱的。

接下来就可以进入本篇的正题--生命周期 顾名思义,生命周期吒听起来就跟人的生老病死相似。那么在编程中说生命周期,大家大概也能想到就是对象的创建、销毁和状态的改变。与iOS类似,RN中也有生命周期。所谓生命周期,其实就是一个对象从开始生成到最后消亡所经历的状态。理解生命周期,其实对你合理开发程序也是有很大帮助的。那么现在看看一张从网上顺来的图~(大家资源共享嘛)

RN的生命周期可以分为三个阶段 实例化阶段: 在初始化阶段会调用一下5个方法: getDefaultProps:这个函数用于初始化一些默认的属性。在组件实例创建前调用,多个实例间共享引用。注意:如果父组件传递过来的Props和你在该函数中定义的Props的key一样,那么它将会被覆盖。

getInitialState:该函数用于对组件的一些状态进行初始化。 可以将控制组件状态的一些变量在这里初始化(通过this.state来获取值,通过this.setState来修改值)。这里值得一提的是,为了在使用中不出现空值,建议初始化state的时候尽可能给每一个可能用到的值都赋一个初始值。 getInitialState 通常在createClass方法创建组件的时候用到,与此类似,在es6中用 constructor构造器方法也可以用来初始化状态值,只不过是用在class 创建的组件 。

componentWillMount:看字面上的意思,它其实就是在告诉一下别人,我的组件即将要被渲染啦。其实它跟oc中的viewWillAppear是极其相似的。这个方法它是在render之前被调用,也就是说它在组件即将显示时调用。而且仅调用一次,可以用于改变state操作。 可以在代码中做一个小的Demo,查看先后顺序。 首先在React中先导入AlertIOS组件,这个组件类似于iOS中的弹窗。用它可以验证方法的调用顺序。 在类中写上componentWillMount(){}方法和render方法。

export default class Test extends Component {
      componentWillMount(){
            AlertIOS.alert('WillMount');
}
  render(){
        return (
              <View sytle={styles.container}>
                    {AlertIOS.alert('render')}
            </View>
);
}
}

效果图如下:

从效果图中可以得知,RN生命周期方法componentWillMount确实在render方法前。那么现在对Render方法做出说明。 render函数用来返回组件构成的Dom,比如说在我们看到的第一个RN界面,返回的那个view。解释一下Dom,与html页面相似,这里的Dom说的就是每一个组件。比如说view,比如说text。每个用标签创建的组件其实都可以看做是一个节点。注意,在这里只能返回一个顶级的元素哦。 componentDidMount:在render渲染之后,组件加载成功并被渲染出来生成真实DOM,生成完毕后会调用这个函数了。这个函数通常是用来做一些如网络请求等加载数据的操作。通常是第一次加载的数据。因为这个时候UI已经被创建出来了,所以在这个函数中请求数据,不会出现UI上的错误。在浏览器端(React),我们可以通过this.getDOMNode()来拿到相应的DOM节点。 在这里我们也对它的顺序与前面两个方法进行测试。

componentDidMount(){
  AlertIOS.alert('DidMount')
}

结果……你会发现,无论你如何按command+r刷新都不会弹出componentDidMount方法吖。恩~想想你们疑惑的样子就开心啊。悄悄地告诉你,alertios的alert方法只会弹出两次,这个效果是react native的特性,生命周期方法,在这里最多只能触发两次。 ok,以上就是RN生命周期初始化的阶段。

当程序执行完了初始化阶段最后调用的componentDidMount函数之后,程序就开始正常的运行起来,这个时候就进入了存在阶段。

那么我们来看看在运行阶段中将会与哪些函数相爱相杀吧 其实在运行阶段中,会分为两种改变。一种是属性的改变,那么另一种就是状态的改变啦。其实属性发生改变也可能会引起状态的改变呢。 那么我们首先来看属性变化调用的方法,componentWillReceiveProps(nextProps):这个方法是说props改变(父容器来更改或是redux),将会调用该函数。新的props将会作为参数传递进来,老的props可以根据this.props来获取。我们可以在该函数中对state作一些处理。注意:在该函数中更新state不会引起二次渲染。 无论是状态还是属性改变,都会调用一个方法。

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。

最后,来到销毁阶段 执行销毁阶段的情况有多种,如:当系统遇到错误而崩溃时;系统空间不足时;APP被用户推出时,等等等等。 当遇到上述问题时,系统就会进入销毁阶段,这个阶段只有一个过程:componentWillUnmount,这个方法用来清空一些无用内容,如:点击事件的Listener等。 销毁阶段是程序执行的出口,只要执行了销毁阶段,就表示程序已经正常或是不正常的消亡了。 ok,以上呢就是RN生老病死的详解。

有些事情,从一开始就注定了如夏花般绚烂。 有些代码,到最后结束还是如秋叶般静美。 悄然无声……

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏软件开发

前端MVC Vue2学习总结(三)——模板语法、过滤器、计算属性、观察者、Class 与 Style 绑定

Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,...

647100
来自专栏Java3y

Juqery就是这么简单

什么是Jquery? Jquey就是一款跨主流浏览器的JavaScript库,简化JavaScript对HTML操作 就是封装了JavaScript,能够简化我...

34750
来自专栏更流畅、简洁的软件开发方式

基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)

好久没发帖子了,又加了不少的功能呀。(图片仅是测试,不代表什么表情。) 本来我也想写一个2007的总结的,但是看到很多人都写了,我就不凑热闹了,写点和代码有关...

20050
来自专栏liuchengxu

Vim 文本对象指南 (1)

本文还是介绍一些基本内容, 关于插件使用, 可以查看完整配置 space-vim.

9820
来自专栏熊二哥

Javascript快速入门(上篇)

Javascript的熟练之路,小弟来了。 ? JavaScript简介:JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,...

20850
来自专栏漫漫前端路

在 Vue 中使用 TypeScript 的一些思考(实践)

两种形式输出结果一致,同是创建一个 Vue 子类,但在书写组件选项如 props,mixin 时,有些不同。特别是当你使用 Vue.extend() 时,为了让...

41720
来自专栏Coding迪斯尼

使用组件的state机制实现屏幕取词

12220
来自专栏LanceToBigData

SpringBoot(四)之thymeleaf的使用

这篇文章将更加全面详细的介绍thymeleaf的使用。thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎。...

648100
来自专栏对角另一面

读Zepto源码之Selector模块

Selector 模块是对 Zepto 选择器的扩展,使得 Zepto 选择器也可以支持部分 CSS3 选择器和 eq 等 Zepto 定义的选择器。 在阅读本...

20900
来自专栏分布式系统和大数据处理

Go语言Tips

转型到Go以后,因为语言的不熟悉,以往很常见的一些操作有时候也需要去Google一下。这里将一些结果记录下来,方便日后查阅。

15120

扫码关注云+社区

领取腾讯云代金券