4) React Native 入门项目与解析

通过编写的第二篇文章可以成功创建一个新项目,即直接利用以下语句创建:

//命令行创建项目:
react-native init AwesomeProject

创建成功后,刚入门的我们主要关注两个文件:
1)iOS项目目录下的AppDelegate.m
为将iOS项目连接js文件的入口,以及相关初始化操作。
2)根目录下的index.ios.js
为iOS对应的js入口文件。

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

1. AppDelegate.m 代码如下:

#import "AppDelegate.h"

//  React Native相关头文件
#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"

@implementation AppDelegate

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

  /* 
   当应用开始运行的时候,RCTRootView将会从以下的URL中加载应用:(本地调试的时候是直接在本地服务器中的index.ios加载,发布时设置有所不同)
   重新调用了你在运行这个App时打开的终端窗口,它开启了一个 packager 和 server 来处理上面的请求。
   在 Safari 中打开那个 URL;你将会看到这个 App 的 JavaScript 代码
  */
  [[RCTBundleURLProvider sharedSettings] setDefaults];
  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

  // RCTRootView是一个UIView容器,承载着React Native应用。同时它也提供了一个联通原生端和被托管端的接口。
  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视图封装到原生组件中。(用户能看到的一切内容都来源于这个RootView,所有的初始化工作也都在这个方法内完成。)

解析:
通过RCTRootView的初始化函数你可以将任意属性传递给React Native应用。
参数initialProperties必须是NSDictionary的一个实例。
这一字典参数会在内部被转化为一个可供JS组件调用的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调用上面定义的参数。
this为AppRegistry.registerComponent注册的组件(下面会讲到)

RCTRootView同样提供了一个可读写的属性appProperties。在appProperties设置之后,React Native应用将会根据新的属性重新渲染。当然,只有在新属性和之前的属性有区别时更新才会被触发。
(注意: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'; // 全局进入严格模式(目前发现不用也行)
/**< 
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。
*/

//导入一些必要的模块
//React Native内置的组件可以直接通过import { xxx } from 'react-native' 进行导入,当然也可以自定义组件。
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity
} from 'react-native';

//类,这是默认的载入类,继承自Component,Component类(组件)似于Android和iOS中的View
//这里为创建一个组件
class AwesomeProject extends Component {
  
  //构造器 ,每个组件都拥有自己的属性(props)和状态(state)
  //调用this.setState更改状态text或者isTouchDown时,组件会触发render函数进行渲染更新   
  constructor(props) {
     super(props);
     this.state = {
       text:'Welcome to React Native!',
       isTouchDown:false
      };
   }  
  
  //在最初的渲染之前调用一次,可在里面进行预处理操作
  //在React中,设置this.state会导致重新渲染,但是componentWillMount设置this.state并不会对导致render调用多次
  //之后会对component的生命周期进一步解释
  componentWillMount() {
  }
  
  //渲染函数,用来渲染实际的Component可视部分
  render() {
    //var定义变量,根据状态值改变对应值
    var welcomeText = this.state.text;
    var bgcolor;
    if (this.state.isTouchDown) {
      bgcolor = '#c5c5ab';
    } else {
      bgcolor = '#F5FCFF';
    }
    console.log('testtststststts');

    //返回的即界面显示内容
    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>
    );
  }

  //  自定义函数
  touchDown() {
    //  console.log 控制台打印,可打印值,多用于调试
    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. 基础概念解释

1)组件

代码中的 Text, View, TouchableOpacity均为基础组件。AwesomeProject则是自己创建的组件,也作为项目的入口组件。
在React Native项目中,所有展示的界面,都可以看做是一个组件(Component)只是功能和逻辑上的复杂程度不同。每一个是许许多多小的组件拼成的,每个小的组件也有自己对应的逻辑。

2)组件的状态与属性

组件本质上是状态机,输入确定,输出一定确定。组件把状态与结果一一对应起来,组件中有state与prop(状态与属性)。

属性(props)是标签里面的属性, 组件之前通过标签的属性来传递数据,由父组件传递给子组件(单向的属性传递)。
如果component的某些状态由外部所决定,并且会影响到component的render,那么这些状态就应该用props表示。
例如:一个下拉菜单的component,有哪些菜单项,是由这个component的使用者和使用场景决定的,那么“菜单项”这个状态,就应该用props表示,并且由外部传入。

状态(state)是子组中的状态,内部的事件方法或者生命周期方法都可以调用this.setState来变更,当状态发生变化的同时,组件也会触发render函数进行渲染更新。
如果component的某些状态需要被改变,并且会影响到component的render,那么这些状态就应该用state表示。
例如:一个购物车的component,会根据用户在购物车中添加的产品和产品数量,显示不同的价格,那么“总价”这个状态,就应该用state表示。


这篇文章利用了一个很简单的例子去具体解析了React Native的基本代码,最主要想理解组件的概念,由此可以更好的去理解别人的代码,,接下去为了更好的入门,会继续写两篇文章分别介绍React Native用到的js基础、react基础,以及介绍组件的生命周期。

正在写React Native的学习教程ing,是一边研究一边编写的,已有的成果如下:
1) React Native 简介与入门
2) React Native 环境搭建和创建项目(Mac)
3) React Native 开发之IDE

  1. React Native 入门项目与解析
    5) React Native 相关JS和React基础
    6) React Native 组件生命周期(ES6)
    7) React Native 集成到原生项目(iOS)
    8) React Native 与原生之间的通信(iOS)
    9) React Native 封装原生UI组件(iOS)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容