React Native--組件Component

我的博客原文地址

創建一個Component

一個組件類可以像前面Hello World工程中那樣通過 class HelloWorldAppp extends Component 來創建,或者通過React.createClass來創建,並且提供一個render方法以及其他可選的生命週期函數、組件相關的事件或方法定義。

因此,HelloWorldAppp和下面的實現方法是等價的:

var HelloWorldAppp = React.createClass({
  render() {
    return (
      <View

      </View>
    );
  },
});

通過繼承Component實現的組件中如果實現getDefaultProps getInitialState等方法時,會有下面警告:

Warning: getDefaultProps was defined on HelloWorldAppp, a plain JavaScript class. This is only supported for classes created using React.createClass. Use a static property to define defaultProps instead.

React組件生命週期

先來看一段代碼:

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

var clickTime = 0;
var HelloWorldAppp = React.createClass({
  getDefaultProps(){
    console.log("getDefaultProps")
    return {title:"HelloWorld"}
  },
  getInitialState(){
    console.log("getInitialState")
   return {content:"點擊屏幕任意位置"}
  },
  componentWillMount(){
    console.log("componentWillMount")
  },
  componentDidMount(){
    console.log("componentDidMount")
  },
  shouldComponentUpdate(nextProps,nextState){
    console.log("shouldComponentUpdate")
    return true
  },
  componentWillUpdate(nextProps,nextState){
    console.log("componentWillUpdate")
  },
  componentDidUpdate(prevProps,prevState){
    console.log("componentDidUpdate")
  },
  render() {
    console.log("render")
    return (
      <TouchableHighlight
        onPress={() => this.backgorundClicked()}
        underlayColor = '#ddd'
        style = {styles.container}
        >
        <Text style={styles.welcome}>{clickTime > 0 ? this.state.content : this.props.title + " \n " + this.state.content}</Text>
      </TouchableHighlight>
    );
  },
  backgorundClicked(){
    clickTime++
    this.setState({
      content:"第"+clickTime+"次點擊"
    });
  }
});

AppRegistry.registerComponent('AwesomeProject', () => HelloWorldAppp);

const styles = StyleSheet.create({
    container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  title_text:{
    fontSize:18,
  }

});

然後認識一下組件中的一些函數:

  • getDefaultProps: 用來設置組件屬性的默認值。通常會將固定的內容放在這個過程中進行初始化和賦值,一個控件可以利用this.props獲取在這裏初始化它的屬性,由於組件初始化後,再次使用該組件不會調用getDefaultProps函數,所以組件自己不可以自己修改props(即:props可認爲是隻讀的),只可由其他組件調用它時在外部修改。
    getDefaultProps並不是在組件實例化時被調用,而是在createClass時被調用,返回值會被緩存。也就是說,不能在getDefaultProps中使用任何特定的實例數據。
  • getInitialState: 這裏是對控件的一些狀態進行初始化,由於該函數不同於getDefaultProps,在以後的過程中,會再次調用,所以可以將控制控件的狀態的一些變量放在這裏初始化,如控件上顯示的文字,可以通過this.state來獲取值,通過this.setState來修改state值,修改方式如下:
    this.setState({
      content:"第"+clickTime+"次點擊"
    });

值得注意的是,一旦調用了this.setState方法,控件必將調用render方法,對控件進行再次的渲染,不過,React框架會自動根據DOM的狀態來判斷是否需要真正的渲染。

  • render:上面已經說過render是一個組件必須有的方法,形式爲一個函數,並返回JSX或其他組件來構成DOM,和Android的XML佈局、WPF的XAML佈局類似,只能返回一個頂級元素。

生命週期函數

  • 裝載組件
    • componentWillMount:這個方法被調用時期是組件將要被加載在視圖上之前,功能比較少,即:render一個組件前最後一次修改state的機會。
    • componentDidMount:即調用了render方法後,組件加載成功並被成功渲染出來以後所執行的hook函數,一般會將網絡請求等加載數據的操作,放在這個函數裏進行,來保證不會出現UI上的錯誤.
  • 更新組件狀態
    存在期主要是用來處理與用戶的交互,如:點擊事件,都比較簡單,也不是很常用,具體有以下幾個過程:
    • componentWillReceiveProps:指父元素對組件的props或state進行了修改。
    • shouldComponentUpdate:一般用於優化,可以返回false或true來控制是否進行渲染
    • componentWillUpdate:組件刷新前調用,類似componentWillMount
    • componentDidUpdate:更新後的hook
  • 卸載(刪除)組件
    銷燬期,用於清理一些無用的內容,如:點擊事件Listener。
    • componentWillUnmount

上面函數的調用順序是:

  • 創建時
    getDefaultProps
    getInitialState
    componentWillMount
    render
    componentDidMount
  • 更新shi
    shouldComponentUpdate
    componentWillUpdate
    render
    componentDidUpdate

總得來講,React Native組件的生命週期,經歷了Mount->Update->Unmount這三個大的過程,即從創建到銷燬的過程,如果藉助Android和iOS的開發思想,那麼React Native組件的生命週期就更容易理解了。那麼,我們構建一個React Native控件也就能夠知道如何下手,如何控制和優化。經過一層一層的封裝和調用,一個完整的React Native應用也就構建出來了。

Props(屬性)和 State(狀態)

Props 就是組件的屬性,由外部通過 JSX 屬性傳入設置,一旦初始設置完成,就可以認爲 this.props 是不可更改的,所以不要輕易更改設置 this.props 裏面的值(雖然對於一個 JS 對象你可以做任何事)。

class MyText extends Component{
  render() {
    return(
      <Text style={this.props.style}>{this.props.content}</Text>
      );
  }
}

class HelloWorldAppp extends Component{
  render() {
    return (
      <MyText style={styles.welcome} content="HelloWorld"/>
    );
  }
}

State 是組件的當前狀態,可以把組件簡單看成一個“狀態機”,根據狀態 state 呈現不同的 UI 展示。一旦狀態(數據)更改,組件就會自動調用 render 重新渲染 UI,這個更改的動作會通過 this.setState 方法來觸發。

class HelloWorldAppp extends Component{
  constructor(props) {
    super(props);
    this.state = {showText:"Test"};
  }
  render() {
    return (
      <View>
          <Text style={styles.title_text}>{this.state.showText}</Text>
      </View>

    );
  }
}

refs

ref是React中的一種屬性,當render函數返回某個組件的實例時,可以給render中的某個虛擬DOM節點添加一個ref屬性。要獲取一個React組件的引用,可以使用ref來獲取你擁有的子組件的引用。

var HelloWorldAppp = React.createClass({
    render() {
      console.log("render");
    return (
      <View style={styles.container}>
        <TextInput style={styles.welcome}  ref="mytestinput"></TextInput>

        <Text style={styles.welcome} onPress={this.blur}>清除焦點</Text>
        <Text style={styles.welcome} onPress={this.focus}>獲取焦點</Text>
      </View>
    );
  },
  focus(){
    if(this.refs.mytestinput != null){
      this.refs.mytestinput.focus();
    }
  },
  blur(){
    if(this.refs.mytestinput != null){
      this.refs.mytestinput.blur();
    }
  }
});

在這個例子中,我們通過this.refs.mytestinput獲取輸入框實例,來實現獲取焦點和清除焦點。

組件之間通信

通過上面的講解我們可以知道:

  • 父組件調用子組件:可以通過this.props方法。
  • 子組件調用父組件:通過回調函數;
  • 兄弟組件:通過其父組件;通過ref來實現;
  • 沒有關聯的組件:通過發送事件:Event Emitter/Target/Dispatcher或者可以通過ref來實現。
  • Redux
  • Flux

這部分後面再介紹。

發佈了190 篇原創文章 · 獲贊 64 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章