React Native 组件的生命同期分为初始化阶段、存在阶段、销毁阶段。
实例化阶段
实例化阶段是RN组件生命周期中最常用的阶段,该阶段是组件的构建、展示,该阶段中的几个方法功能解析如下:
getDefaultProps:
该函数用于初始化一些默认的属性。在组件中可以利用 this.props.* 的方式获取在这个函数中定义的属性。
注意:this.props是只读的,组件中不能修改
getInitialState:
该函数用于对组件的一些状态进行初始化。
可以将控制组件状态的一些变量在这里初始化(通过this.state来获取值,通过this.setState来修改值)
注意:一旦调用了this.setState方法,组件就一定会调用render函数对组件进行再次渲染,不过React框架会自动根据DOM的状态来判断是否需要真正的渲染。
render:
render函数返回JSX或者其他组件来构成DOM(注意:只能返回一个顶级元素)
在render函数中,只可以通过this.props 和 this.state来访问在之前的函数中初始化的数据。
componentDidMount:
在调用了render函数,组件加载成功并被成功渲染出来以后,所要执行的后续操作(如网络请求等加载数据的操作),一般会在这个函数中进行。因为UI已经被渲染出来了,所以放在这个函数中里德的请求操作,不会出现UI上的错误。
注意:如果想要在主类中书写多个生命周期函数(getInitialState等),需要使用 ES5 的语法,如果用 ES6 的语法会报错。
存在和销毁阶段
当程序执行完了初始化阶段最后调用的 componentDidMount 函数之后,程序就开始正常的运行起来,此时就进入了存在阶段。
存在阶段执行流程:
程序在运行过程中,如果对this.state 或者 this.props 进行了修改,那么就会触发存在阶段的多个函数(调用流程如上图所示)。
无论是修改this.state 还是 this.props,系统都会调用 shouldComponentUpdate 函数,判断视图是否需要渲染,如果不需要,则忽略本次修改状态;如果需要则在通过 componentWillUpdate 函数准备之后,重新调用 render 函数进行渲染。
注意:this.state 使用的是状态机制,即将组件看成一个状态机,一开始有一个初始状态,然后在用户互动的时候改变组件状态,从而触发重新渲染UI。
销毁阶段执行流程:
执行销毁阶段的情况有多种,如:当系统遇到错误而崩溃时;系统空间不足时;APP被用户推出时,等等等等。
当遇到上述问题时,系统就会进入销毁阶段,这个阶段只有一个过程:componentWillmount, 这个方法用来清空一些无用内容,如:点击事件的 Listener 等。
注意:销毁阶段是程序执行的出口,只要执行了销毁阶段,就表示程序已经自然或不自然的退出了。
状态机
上面说到,在RN生命周期初始化阶段的 getInitialState 方法中用到了状态机的原理,状态机原理即通过修改程序中状态机中的属性的值,来达到改变界面的目的。状态机的一段示例代码如下:
var BTouchableDemo = React.createClass({
getInitialState(){
return {
content: '触摸事件响应器'
}
},
render() {
return (
<View style={styles.containerStyle}>
<TouchableOpacity
onPress={() => this.changeResultContent('点击')}
onPressIn={() => this.changeResultContent('按下')}
onPressOut={() => this.changeResultContent('抬起')}
onLongPress={() => this.changeResultContent('长按')}>
<View style={styles.loginContainerStyle}>
<Text style={styles.loginTextStyle}>TouchableOpacity</Text>
</View>
</TouchableOpacity>
<Text style={styles.resultStyle}>{this.state.content}</Text>
</View>
);
},
changeResultContent(content) {
this.setState({
content: content
});
}
});
可以看到,上面一段代码通过修改状态机中的content属性,来修改底部的 Text中的文本信息。
注意: 如果是要获取状态机中的属性值,则可以直接通过 this.state.* 的方式获取;如果想要设置(更新)状态机中某个属性的值,则必须要通过 this.setState 方法设置。
ES5 和 ES6 代码的比较
ES6 的代码风格相对于 ES5 有很大的改变,实例化阶段的几个方法(render,getDefaultProps,getInitialState)在两个中的差别很大。
使用Es5编写:
var CLifeCycle = React.createClass({
// 设置一些常量(程序中不可改变的量)
getDefaultProps(){
return {name: 'Jack'};
},
// 设置状态机属性(程序中可以改变的量)
getInitialState(){
return {age: 20};
},
// 渲染布局
render(){
return (
<View style={styles.containerStyle}>
<Text style={styles.textStyle}>我是ES 5语法模板</Text>
</View>
);
}
});
使用ES6 编写:
export default class CLifeCycle extends Component {
// 设置状态机属性(程序中可以改变的量)
constructor(props) {
super(props);
this.state = {age: 20};
}
// 渲染布局
render() {
return (
<View style={styles.containerStyle}>
<Text style={styles.textStyle}>我是ES 6语法模板</Text>
</View>
);
}
}
// 设置一些常量(程序中不可改变的量)的数据类型
CLifeCycle.propTypes = {name: React.PropTypes.string};
// 设置一些常量(程序中不可改变的量)的默认值
CLifeCycle.defaultProps = {name: 'Jack'};
获取真实DOM节点
在RN中,组件并不是真正的DOM节点,而是存在于内存中的一种数据结构,叫做虚拟DOM。只有当它插入文档之后,才会称为真正的DOM。
如果想要通过组件获取真正的DOM节点,可以使用 ref 属性设置标记,然后在需要使用的地方通过 this.refs.* 访问这个组件。