跨平台开发RN-组件的生命周期
生命周期
-
在React Native中,组件的生命周期大致可以分为3个阶段:实例化阶段,存在阶段,销毁阶段,其中最常接触的为实例化阶段,这个阶段负责组件的构建和展示的时间,需要我们根据几个函数的调用过程,控制好组件的展示和逻辑处理。
实例化阶段函数功能分析
getDefaultProps:
- 该函数用于初始化一些默认的属性,通常会将固定的内容放到这个函数中进行初始化和赋值。相当于iOS的
+load
方法。只会调用一次。 - 在组件使用中,我们可以利用
this.props
获取在这里初始化的属性值,由于组件初始化后,再次使用该组件不会调用getDefaultProps
函数,所以组件自己不可以修改props
,只可由其他组件调用它时再外部进行修改。
- 该函数用于初始化一些默认的属性,通常会将固定的内容放到这个函数中进行初始化和赋值。相当于iOS的
getInitialState:
- 该函数用于对组件一些状态进行初始化,最新的修改为
constructor:
方法,相当于iOS中设置对象的成员变量 - 该函数不同于getDefaultProps,在以后的过程中,会再次调用,所以可以将控制控件状态的一些变量放在这里初始化,比如控件上显示的文字,可以通过this.state来获取值,通过this.setState来修改state值。
- 注意:一旦调用了this.setState方法,组件一定会调用render方法,对组件进行再次渲染,不过,React框架会根据DOM的状态自动判断是否需要真正渲染.从而达到了数据驱动视图
-
举例使用
constructor(props) { super(props); this.state = { clickText: "开始点击按钮", count: 1, detailContent: true } } ... clickButton(){ const { count } = this.state; this.setState({ clickText: "我点击了按钮", count: count + 1, detailContent: false }) } render() { console.log("render1111"); return ( <View style={styles.container}> <Text>欢迎来到首页</Text> <TouchableOpacity onPress={() => Actions.notice()} > <Text>跳转到公告页</Text> </TouchableOpacity> <Text style={*color: 'blue', fontSize: 40}}>{this.state.count}</Text> <TouchableOpacity style={styles.button} onPress={() => this.clickButton()} > <Text>{this.state.clickText}</Text> </TouchableOpacity> <HomeDetails detailContent={this.state.detailContent}/> </View> ) }
- 该函数用于对组件一些状态进行初始化,最新的修改为
componentWillMount:
- 组件将要被加载到视图之前调用,相当于iOS的
ViewVillAppear
- 组件将要被加载到视图之前调用,相当于iOS的
render:
- 相当于iOS的ViewDidLoad
- render是一个组件必须有的方法,本质上是一个函数,并返回JSX或其他组件来构成DOM.
- 注意:只能返回一个顶级元素。
- 此外在render中,可以通过
this.props/this.state
来访问在之前初始化的值。
- componentDidMount:
- 在调用了render方法,组件加载成功并被成功渲染出来之后,所要执行的后续操作,一般都会在这个函数中进行,比如经常要面对的网络请求等加载数据操作
- 因为UI已经成功渲染,而且这里面是异步的,所以放在这个函数进行数据的请求等复杂的操作,不会出现UI错误
存在阶段函数功能分析
shouldComponentUpdate:一般用于优化,可以返回false或true来控制是否进行渲染(true 的话进行下2步操作,false不会进行下去)
componentWillUpdate: 组件刷新前调用
componentDidUpdate:更新后
componentWillReceiveProps:指父元素对组件的props或state进行了修改
销毁阶段函数功能分析
componentWillUnmount
- 用于清理一些无用的内容,比如:定时器清除
生命周期方法总结
获取真实的Dom节点
- 在H5中,我们可以通过各种选择器来获取到指定的标签(Dom节点),那么RN中如何获取呢?
- 在React Native中,组件并不是真实的DOM节点,而是存在于内存中的一种数据结构,叫虚拟DOM
- 只有当它插入文档后,才会变成真实的DOM
- 根据React的设计,所有DOM变动,都现在虚拟DOM上发生,然后再将实际发生变动的部分,反映在真实DOM上,这种算法叫做DOM diff,它可以极大提高网页的性能表现。
-
有时需要从组建获取真实DOM节点,这时就需要到ref属性
class Enty4 extends Component { //初始化成员变量title constructor(props) { super(props); this.state = { title: '不透明触摸', }; } render() { return ( <View ref="TopView" style={styles.container}> {/* 包装点击效果*/} <TouchableOpacity //设置点击透明度 activeOpacity={0.5} onPress={() => this.activeEvent('点击')} onPressIn={() => this.activeEvent('按下')} onPressOut={() => this.activeEvent('抬起')} onLongPress={() => this.activeEvent('长按')}> <View style={*margin: 50, backgroundColor: 'red'}}> <Text ref="event">常用点击事件</Text> </View> </TouchableOpacity> {/*点击上面的View展示不同的title*/} <View> <Text ref="TestView">{this.state.title}</Text> </View> </View> ); } //修改title的值 activeEvent(event) { this.setState({ title: event, }); // 拿到指定的Dom节点 this.refs.TopView; this.refs.event; } }
什么是DOM diff算法
- Web界面由DOM树来构成,当其中某一部分发生变化时,其实就是对应的某个DOM节点发生了变化,在React中,构建UI界面的思路是由当前状态决定界面,前后两个状态就对应两套界面,然后由React来比较两个界面的区别,这就需要对DOM树进行Diff算法分析。
ES5与ES6的区别
es5
,es6
都是对ecmascript
规范的补充, 其中箭头函数()=>()是ES6
独有的。- 区别1: 创建组件
- 组件是一个自定义的js对象,在es5中使用
React.createClass()
;在es6
中必须继承React.component
,然后进行创建。
- 组件是一个自定义的js对象,在es5中使用
- 区别2:组件的属性
props
-
在
ES6
中,其为属性:defaultProps(可以标识static定义在class内,也可以定义在class外)
,而在ES5
中,其为方法:getDefaultProps: function(){return {name:value}}
;
-
-
区别3:组件的状态state
相关代码:
-
index.js
import React, {Component} from 'react'; import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; import {Actions} from 'react-native-router-flux'; import HomeDetails from './HomeDetails'; export default class Home extends Component { constructor(props) { super(props); this.state = { clickText: "开始点击按钮", count: 1, detailContent: true } } componentWillMount() { console.log("componentWillMount1111"); } shouldComponentUpdate(nextProps, nextState){ console.log(this.state.detailContent,'detailContent'); if (this.state.count !== nextState.count) { console.log("shouldComponentUpdate1111---组件需要更新"); return true; } return false; } componentWillUpdate(){ console.log("componentWillUpdate1111---组件将要更新"); } componentDidUpdate(){ console.log("componentDidUpdate1111---组件更新完毕"); } componentDidMount() { console.log("componentDidMount1111"); } componentWillUnmount() { console.log("componentWillUnmount1111"); } clickButton(){ const { count } = this.state; this.setState({ clickText: "我点击了按钮", count: count + 1, detailContent: false }) } render() { console.log("render1111"); return ( <View style={styles.container}> <Text>欢迎来到首页</Text> <TouchableOpacity onPress={() => Actions.notice()} > <Text>跳转到公告页</Text> </TouchableOpacity> <Text style={*color: 'blue', fontSize: 40}}>{this.state.count}</Text> <TouchableOpacity style={styles.button} onPress={() => this.clickButton()} > <Text>{this.state.clickText}</Text> </TouchableOpacity> <HomeDetails detailContent={this.state.detailContent}/> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center" }, button: { width: 250, height: 60, backgroundColor: 'red', borderRadius: 10, alignItems: 'center', justifyContent: 'center' } });
-
子组件
HomeDtails.js
import React, {Component} from 'react'; import { View, Text, StyleSheet } from 'react-native'; export default class HomeDetails extends Component { constructor(props) { super(props); this.state = {} } componentWillMount() { } componentWillReceiveProps(nextProps){ console.log(this.props.detailContent,'this--->>componentWillReceiveProps'); console.log(nextProps.detailContent,'next--->>componentWillReceiveProps') } componentDidMount() { } componentWillUnmount() { } render() { return ( <View style={styles.container}> <Text>欢迎HomeDetails</Text> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center" } });