4) React Native 入門項目與解析

通過編寫的第二篇文章可以成功創(chuàng)建一個新項目,即直接利用以下語句創(chuàng)建:

//命令行創(chuàng)建項目:
react-native init AwesomeProject

創(chuàng)建成功后,剛?cè)腴T的我們主要關(guān)注兩個文件:
1)iOS項目目錄下的AppDelegate.m
為將iOS項目連接js文件的入口,以及相關(guān)初始化操作。
2)根目錄下的index.ios.js
為iOS對應(yīng)的js入口文件。

一、 解析iOS項目中的AppDelegate.m

1. AppDelegate.m 代碼如下:

#import "AppDelegate.h"

//  React Native相關(guān)頭文件
#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSURL *jsCodeLocation;

  /* 
   當應(yīng)用開始運行的時候,RCTRootView將會從以下的URL中加載應(yīng)用:(本地調(diào)試的時候是直接在本地服務(wù)器中的index.ios加載,發(fā)布時設(shè)置有所不同)
   重新調(diào)用了你在運行這個App時打開的終端窗口,它開啟了一個 packager 和 server 來處理上面的請求。
   在 Safari 中打開那個 URL;你將會看到這個 App 的 JavaScript 代碼
  */
  [[RCTBundleURLProvider sharedSettings] setDefaults];
  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

  // RCTRootView是一個UIView容器,承載著React Native應(yīng)用。同時它也提供了一個聯(lián)通原生端和被托管端的接口。
  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"AwesomeProject"
                                               initialProperties:nil
                                                   launchOptions:launchOptions];
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

@end

2. RCTRootView

RCTRootView將React Natvie視圖封裝到原生組件中。(用戶能看到的一切內(nèi)容都來源于這個RootView,所有的初始化工作也都在這個方法內(nèi)完成。)

解析:
通過RCTRootView的初始化函數(shù)你可以將任意屬性傳遞給React Native應(yīng)用。
參數(shù)initialProperties必須是NSDictionary的一個實例。
這一字典參數(shù)會在內(nèi)部被轉(zhuǎn)化為一個可供JS組件調(diào)用的JSON對象。

NSArray *imageList = @[@"http://foo.com/bar1.png",
                  @"http://foo.com/bar2.png"];
NSDictionary *propsDict = @{@"images" : imageList};

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"AwesomeProject"
                                               initialProperties: propsDict
                                                   launchOptions:launchOptions];

在js文件中,則是通過this.props.images調(diào)用上面定義的參數(shù)。
this為AppRegistry.registerComponent注冊的組件(下面會講到)

RCTRootView同樣提供了一個可讀寫的屬性appProperties。在appProperties設(shè)置之后,React Native應(yīng)用將會根據(jù)新的屬性重新渲染。當然,只有在新屬性和之前的屬性有區(qū)別時更新才會被觸發(fā)。
(注意:1.可以隨時更新屬性,但是更新必須在主線程中進行,讀取則可以在任何線程中進行。2.更新屬性時并不能做到只更新一部分屬性)

NSArray *imageList = @[@"http://foo.com/bar3.png",
                   @"http://foo.com/bar4.png"];
rootView.appProperties = @{@"images" : imageList};

二、解析js入口文件(index.ios.js)

1. index.ios.js 代碼如下:

'use strict'; // 全局進入嚴格模式(目前發(fā)現(xiàn)不用也行)
/**< 
消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為;
消除代碼運行的一些不安全之處,保證代碼運行的安全;
提高編譯器效率,增加運行速度;
為未來新版本的Javascript做好鋪墊。
*/

//導入一些必要的模塊
//React Native內(nèi)置的組件可以直接通過import { xxx } from 'react-native' 進行導入,當然也可以自定義組件。
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity
} from 'react-native';

//類,這是默認的載入類,繼承自Component,Component類(組件)似于Android和iOS中的View
//這里為創(chuàng)建一個組件
class AwesomeProject extends Component {
  
  //構(gòu)造器 ,每個組件都擁有自己的屬性(props)和狀態(tài)(state)
  //調(diào)用this.setState更改狀態(tài)text或者isTouchDown時,組件會觸發(fā)render函數(shù)進行渲染更新   
  constructor(props) {
     super(props);
     this.state = {
       text:'Welcome to React Native!',
       isTouchDown:false
      };
   }  
  
  //在最初的渲染之前調(diào)用一次,可在里面進行預處理操作
  //在React中,設(shè)置this.state會導致重新渲染,但是componentWillMount設(shè)置this.state并不會對導致render調(diào)用多次
  //之后會對component的生命周期進一步解釋
  componentWillMount() {
  }
  
  //渲染函數(shù),用來渲染實際的Component可視部分
  render() {
    //var定義變量,根據(jù)狀態(tài)值改變對應(yīng)值
    var welcomeText = this.state.text;
    var bgcolor;
    if (this.state.isTouchDown) {
      bgcolor = '#c5c5ab';
    } else {
      bgcolor = '#F5FCFF';
    }
    console.log('testtststststts');

    //返回的即界面顯示內(nèi)容
    return (
      <View style={[styles.container, {backgroundColor: bgcolor}]}>
        <Text style={styles.welcome}>
          {welcomeText}
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
            Shake or press menu button for dev menu
        </Text>
        <TouchableOpacity onPress={this.touchDown.bind(this)}>
          <Text style={[styles.instructions, {backgroundColor: 'green'}]}>
            test touch Me
          </Text>
        </TouchableOpacity>
      </View>
    );
  }

  //  自定義函數(shù)
  touchDown() {
    //  console.log 控制臺打印,可打印值,多用于調(diào)試
    console.log('>>', this.isTouchDown);

    if (!this.state.isTouchDown) {
      this.setState({
        text:'Test Touch Down Success',
        isTouchDown:true
      });
    } else {
      this.setState({
        text:'Test Touch Down Again Success',
        isTouchDown:false
      });
    }
  }

}

//定義樣式
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

//AppRegistry 定義了App的入口,并提供了根組件。
//第一個'AwesomeProject'要與AppDelegate里注冊的moduleName一致
//第二個AwesomeProject則是入口組件,即上面定義的Component類
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

2. 運行效果:

簡單運行效果.png

3. 基礎(chǔ)概念解釋

1)組件

代碼中的 Text, View, TouchableOpacity均為基礎(chǔ)組件。AwesomeProject則是自己創(chuàng)建的組件,也作為項目的入口組件。
在React Native項目中,所有展示的界面,都可以看做是一個組件(Component)只是功能和邏輯上的復雜程度不同。每一個是許許多多小的組件拼成的,每個小的組件也有自己對應(yīng)的邏輯。

2)組件的狀態(tài)與屬性

組件本質(zhì)上是狀態(tài)機,輸入確定,輸出一定確定。組件把狀態(tài)與結(jié)果一一對應(yīng)起來,組件中有state與prop(狀態(tài)與屬性)。

屬性(props)是標簽里面的屬性, 組件之前通過標簽的屬性來傳遞數(shù)據(jù),由父組件傳遞給子組件(單向的屬性傳遞)。
如果component的某些狀態(tài)由外部所決定,并且會影響到component的render,那么這些狀態(tài)就應(yīng)該用props表示。
例如:一個下拉菜單的component,有哪些菜單項,是由這個component的使用者和使用場景決定的,那么“菜單項”這個狀態(tài),就應(yīng)該用props表示,并且由外部傳入。

狀態(tài)(state)是子組中的狀態(tài),內(nèi)部的事件方法或者生命周期方法都可以調(diào)用this.setState來變更,當狀態(tài)發(fā)生變化的同時,組件也會觸發(fā)render函數(shù)進行渲染更新。
如果component的某些狀態(tài)需要被改變,并且會影響到component的render,那么這些狀態(tài)就應(yīng)該用state表示。
例如:一個購物車的component,會根據(jù)用戶在購物車中添加的產(chǎn)品和產(chǎn)品數(shù)量,顯示不同的價格,那么“總價”這個狀態(tài),就應(yīng)該用state表示。


這篇文章利用了一個很簡單的例子去具體解析了React Native的基本代碼,最主要想理解組件的概念,由此可以更好的去理解別人的代碼,,接下去為了更好的入門,會繼續(xù)寫兩篇文章分別介紹React Native用到的js基礎(chǔ)、react基礎(chǔ),以及介紹組件的生命周期。

正在寫React Native的學習教程ing,是一邊研究一邊編寫的,已有的成果如下:
1) React Native 簡介與入門
2) React Native 環(huán)境搭建和創(chuàng)建項目(Mac)
3) React Native 開發(fā)之IDE

  1. React Native 入門項目與解析
    5) React Native 相關(guān)JS和React基礎(chǔ)
    6) React Native 組件生命周期(ES6)
    7) React Native 集成到原生項目(iOS)
    8) React Native 與原生之間的通信(iOS)
    9) React Native 封裝原生UI組件(iOS)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容