跨平台开发RN-组件的生命周期

生命周期

  1. 在React Native中,组件的生命周期大致可以分为3个阶段:实例化阶段,存在阶段,销毁阶段,其中最常接触的为实例化阶段,这个阶段负责组件的构建和展示的时间,需要我们根据几个函数的调用过程,控制好组件的展示和逻辑处理。

    图1

实例化阶段函数功能分析

  1. getDefaultProps:
    1. 该函数用于初始化一些默认的属性,通常会将固定的内容放到这个函数中进行初始化和赋值。相当于iOS的+load方法。只会调用一次
    2. 在组件使用中,我们可以利用this.props获取在这里初始化的属性值,由于组件初始化后,再次使用该组件不会调用getDefaultProps函数,所以组件自己不可以修改props,只可由其他组件调用它时再外部进行修改。
  2. getInitialState:
    1. 该函数用于对组件一些状态进行初始化,最新的修改为constructor:方法,相当于iOS中设置对象的成员变量
    2. 该函数不同于getDefaultProps,在以后的过程中,会再次调用,所以可以将控制控件状态的一些变量放在这里初始化,比如控件上显示的文字,可以通过this.state来获取值,通过this.setState来修改state值。
    3. 注意:一旦调用了this.setState方法,组件一定会调用render方法,对组件进行再次渲染,不过,React框架会根据DOM的状态自动判断是否需要真正渲染.从而达到了数据驱动视图
    4. 举例使用

       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>
           )
       }
      
  3. componentWillMount:
    1. 组件将要被加载到视图之前调用,相当于iOS的ViewVillAppear
  4. render:
    1. 相当于iOS的ViewDidLoad
    2. render是一个组件必须有的方法,本质上是一个函数,并返回JSX或其他组件来构成DOM.
    3. 注意:只能返回一个顶级元素。
    4. 此外在render中,可以通过this.props/this.state来访问在之前初始化的值。
  5. componentDidMount:
    1. 在调用了render方法,组件加载成功并被成功渲染出来之后,所要执行的后续操作,一般都会在这个函数中进行,比如经常要面对的网络请求等加载数据操作
    2. 因为UI已经成功渲染,而且这里面是异步的,所以放在这个函数进行数据的请求等复杂的操作,不会出现UI错误

存在阶段函数功能分析

shouldComponentUpdate:一般用于优化,可以返回false或true来控制是否进行渲染(true 的话进行下2步操作,false不会进行下去)
componentWillUpdate: 组件刷新前调用
componentDidUpdate:更新后
componentWillReceiveProps:指父元素对组件的props或state进行了修改

销毁阶段函数功能分析

  1. componentWillUnmount
    1. 用于清理一些无用的内容,比如:定时器清除

生命周期方法总结

图1

获取真实的Dom节点

  1. 在H5中,我们可以通过各种选择器来获取到指定的标签(Dom节点),那么RN中如何获取呢?
  2. 在React Native中,组件并不是真实的DOM节点,而是存在于内存中的一种数据结构,叫虚拟DOM
  3. 只有当它插入文档后,才会变成真实的DOM
  4. 根据React的设计,所有DOM变动,都现在虚拟DOM上发生,然后再将实际发生变动的部分,反映在真实DOM上,这种算法叫做DOM diff,它可以极大提高网页的性能表现。
  5. 有时需要从组建获取真实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算法

  1. Web界面由DOM树来构成,当其中某一部分发生变化时,其实就是对应的某个DOM节点发生了变化,在React中,构建UI界面的思路是由当前状态决定界面,前后两个状态就对应两套界面,然后由React来比较两个界面的区别,这就需要对DOM树进行Diff算法分析。

ES5与ES6的区别

  1. es5es6都是对 ecmascript规范的补充, 其中箭头函数()=>()是ES6独有的。
  2. 区别1: 创建组件
    1. 组件是一个自定义的js对象,在es5中使用React.createClass();在es6中必须继承React.component,然后进行创建。

    图1

  3. 区别2:组件的属性props
    1. ES6中,其为属性:defaultProps(可以标识static定义在class内,也可以定义在class外),而在ES5中,其为方法:getDefaultProps: function(){return {name:value}};

      图1

  4. 区别3:组件的状态state

    图1

相关代码:

  1. 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'
       }
     });
    
  2. 子组件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"
       }
     });
    
Table of Contents