美文网首页iOS Developer编程知识点
React Native 组件生命周期

React Native 组件生命周期

作者: iOS104 | 来源:发表于2017-03-29 14:26 被阅读96次

在React Native中使用组件来封装界面模块时,整个界面就是一个大的组件,开发过程就是不断优化和拆分界面组件、构造整个组件树的过程。

组件的属性(props)和状态(state)

1. 属性(props)

  • 它是组件的不可变属性(组件自己不可以自己修改props)。
  • 组件自身定义了一组props作为对外提供的接口,展示一个组件时只需要指定props作为节点的属性。
  • 一般组件很少需要对外公开方法(例外:工具类的静态方法等),唯一的交互途径就是props。
  • 所以说它也是父组件与子组件通信的桥梁。
    组件自己不可以自己修改props(即:props可认为是只读的),只可由其他组件调用它时在外部修改。

2. 状态(state)

  • 它是组件的内部状态属性,主要用来存储组件自身需要的数据。
  • 除了初始化时可能由props来决定,之后就完全由组件自身去维护。
  • 组件中由系统定义了setState方法,每次调用setState时都会更新组件的状态,触发render方法重新渲染界面。
  • 需要注意的是render方法是被异步调用的,这可以保证同步的多个setState方法只会触发一次render,这样做是有利于提高性能的。

组件的生命周期

对于自定义组件,除了必须实现的render方法,还有一些其他的可选方法可被调用。这些方法会在组件的不同时期之行,所以也可以说这些方法是组件的生命周期方法。

对于组件的生命周期来说一般分为四个阶段,分别为:
创建阶段、实例化阶段、运行(更新)阶段、销毁阶段。

1. 创建阶段

  • 该阶段主要发生在创建组件类的时候,在这个阶段中会初始化组件的属性类型和默认属性。

  • 这里会初始化一些默认的属性,通常会将固定的内容放在这个过程中进行初始化和赋值,一个控件可以利用this.props获取在这里初始化它的属性

  • 由于组件初始化后,再次使用该组件不会调用getDefaultProps函数,所以组件自己不可以自己修改props(即:props可认为是只读的),只可由其他组件调用它时在外部修改。

//ES6
static defaultProps = {
        autoPlay: false,
        maxLoops: 10,
};  // 注意这里有分号
static propTypes = {
        autoPlay: React.PropTypes.bool.isRequired,
        maxLoops: React.PropTypes.number.isRequired,
        posterFrameSrc: React.PropTypes.string.isRequired,
        videoSrc: React.PropTypes.string.isRequired,
};  // 注意这里有分号

2. 实例化阶段

(1)、 constructor(props)
  • 该阶段主要发生在组件类被调用(实例化)的时候。
  • 组件类被实例化的时候,触发一系列流程:
  • 这里是对控件的一些状态进行初始化,由于该函数不同于getDefaultProps,在以后的过程中,会再次调用,所以可以将控制控件的状态的一些变量放在这里初始化,如控件上显示的文字,可以通过this.state来获取值,通过this.setState来修改state值。
constructor(props){
        super(props);
        this.state = {
            loopsRemaining: this.props.maxLoops,
        };
}
(2)、 componentWillMount()
  • 该函数类似于iOS中的VillWillAppear,在组件即将加载在视图上调用。
  • 这个调用时机是在组件创建,并初始化了状态之后,在第一次绘制 render() 之前。可以在这里做一些业务初始化操作,也可以设置组件状态。这个函数在整个生命周期中只被调用一次。
(3)、 render:

该函数组件必有的,通过返回JSX或其他组件来构成DOM,换言之,就是组件的核心渲染过程。

(4)、 componentDidMount:

调用了render方法后,组件加载成功并被成功渲染出来以后所执行的hook函数,一般会将网络请求等加载数据的操作,放在这个函数里进行,来保证不会出现UI上的错误。

3. 运行(更新)阶段

该阶段主要发生在用户操作之后,或者父组件有更新的时候,此时会根据用户的操作行为,进行相应的界面结构调整。

(1)、 componentWillReceiveProps(nextProps)

当组件接收到新的props时,会触发该函数。在该函数中,通常可以调用setState()来完成对state的修改。

(2)、 shouldComponentUpdate(nextProps, nextState)
  • 返回布尔值(决定是否需要更新组件)
  • 输入参数 nextProps 和上面的 componentWillReceiveProps 函数一样,nextState 表示组件即将更新的状态值。
  • 这个函数的返回值决定是否需要更新组件,如果 true 表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。
(3)、 componentWillUpdate(nextProps, nextState)
  • shouldComponentUpdate返回true或者调用forceUpdate之后,就会开始准更新组件,并调用 componentWillUpdate()。
  • 在这个函数里面,你就不能使用 this.setState 来修改状态。
(4)、render()

再确定需要更新组件时,调用render,根据diff算法,渲染界面,生成需要更新的虚拟DOM数据。

(5)、componentDidUpdate()

除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。

componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以对应起来。区别在于,前者只有在挂载的时候会被调用;而后者在以后的每次更新渲染之后都会被调用。
ps:绝对不要在componentWillUpdate和componentDidUpdate中调用this.setState方法,否则将导致无限循环调用。

4. 销毁阶段

该阶段主要发生组件销亡的时候,触发componentWillUnmount。当组件需要从DOM中移除的时候,通常需要做一些取消事件绑定,移除虚拟DOM中对应的组件数据结构,销毁一些无效的定时器等工作

组件生命周期总体流程图

Paste_Image.png

代码实现

github地址

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity
} from 'react-native';

export default class ReactNativeDemo extends Component {

  //初始化一些不可以修改的值
  static defaultProps = {
    // autoPlay: false,
    // maxLoops: 10,
  };  // 注意这里有分号
  static propTypes = {
    // autoPlay: React.PropTypes.bool.isRequired,
    // maxLoops: React.PropTypes.number.isRequired,
    // posterFrameSrc: React.PropTypes.string.isRequired,
    // videoSrc: React.PropTypes.string.isRequired,
  };

  //初始化一些可以修改的值
  constructor(props) {
    super(props);
    this.state = {
      num: 1,
    }
  }

  //相当于iOS中viewWillAppear
  componentWillMount(){
    console.log('componentWillMount');
    this.onPress = this._onPress.bind(this);
  }

  //相当于iOS中的viewDidLoad 可以在这里做一些复杂操作,如网络请求数据
  componentDidMount(){
    console.log('componentDidMount');
  }

  //组件初始化时不调用,组件接受新的props时调用
  componentWillReceiveProps(nextProps) {
    console.log('componentWillReceiveProps');
  }

  //react性能优化非常重要的一环。组件接受新的state或者props时调用
  shouldComponentUpdate(nextProps, nextState) {
    console.log('shouldComponentUpdate');
    return true;
  }

  //组件初始化时不调用,只有在组件将要更新时才调用
  componentWillUpdate(nextProps, nextState) {
    console.log('componentWillUpdate');
  }

  //组件初始化时不调用,组件更新完成后调用
  componentDidUpdate() {
    console.log('componentDidUpdate');
  }

  //组件将要卸载时调用,一些事件监听和定时器需要在此时清除
  componentWillUnmount() {
    console.log('componentWillUnmount');
  }

  _onPress() {
    this.setState({num : this.state.num + 1});
  }

  render() {
    console.log('render');
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={this.onPress} style={styles.container1}>
          <Text style={styles.button}>{"Press me" + this.state.num}</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },

  container1: {
    backgroundColor: `gray`,
    width: 200,
    height: 200,
    justifyContent: 'center',
    alignItems: 'center',
  },

  button: {
    color: 'red',
    fontSize: 20,
    textAlign: 'center',
  },
});

AppRegistry.registerComponent('ReactNativeDemo', () => ReactNativeDemo);

输出结果:


Paste_Image.png

相关文章

网友评论

    本文标题:React Native 组件生命周期

    本文链接:https://www.haomeiwen.com/subject/unieottx.html