React Native入门项目与解析

React Native是最近非常火的一个话题,介绍如何利用React Native进行开发的文章和
首页 新闻资讯 行业资讯 React Native入门项目与解析

 通过React Native 环境搭建和创建项目(Mac)可以成功创建一个新项目,即直接利用以下语句创建:

复制

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

  • 2.

  • 3.

创建成功后,刚入门的我们主要关注两个文件:

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
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

  • 29.

  • 30.

  • 31.

  • 32.

  • 33.

  • 34.

  • 35.

  • 36.

  • 37.

  • 38.

  • 39.

  • 40.

  • 41.

  • 42.

  • 43.

  • 44.

  • 45.

  • 46.

  • 47.

  • 48.

  • 49.

  • 50.

  • 51.

  • 52.

  • 53.

  • 54.

  • 55.

  • 56.

  • 57.

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];
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

在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};
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

二、解析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);
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

  • 29.

  • 30.

  • 31.

  • 32.

  • 33.

  • 34.

  • 35.

  • 36.

  • 37.

  • 38.

  • 39.

  • 40.

  • 41.

  • 42.

  • 43.

  • 44.

  • 45.

  • 46.

  • 47.

  • 48.

  • 49.

  • 50.

  • 51.

  • 52.

  • 53.

  • 54.

  • 55.

  • 56.

  • 57.

  • 58.

  • 59.

  • 60.

  • 61.

  • 62.

  • 63.

  • 64.

  • 65.

  • 66.

  • 67.

  • 68.

  • 69.

  • 70.

  • 71.

  • 72.

  • 73.

  • 74.

  • 75.

  • 76.

  • 77.

  • 78.

  • 79.

  • 80.

  • 81.

  • 82.

  • 83.

  • 84.

  • 85.

  • 86.

  • 87.

  • 88.

  • 89.

  • 90.

  • 91.

  • 92.

  • 93.

  • 94.

  • 95.

  • 96.

  • 97.

  • 98.

  • 99.

  • 100.

  • 101.

  • 102.

  • 103.

  • 104.

  • 105.

  • 106.

  • 107.

  • 108.

  • 109.

  • 110.

  • 111.

  • 112.

  • 113.

  • 114.

  • 115.

  • 116.

  • 117.

  • 118.

  • 119.

  • 120.

  • 121.

  • 122.

  • 123.

  • 124.

  • 125.

  • 126.

  • 127.

  • 128.

  • 129.

  • 130.

  • 131.

  • 132.

  • 133.

  • 134.

  • 135.

  • 136.

  • 137.

  • 138.

  • 139.

  • 140.

  • 141.

  • 142.

  • 143.

  • 144.

  • 145.

  • 146.

  • 147.

  • 148.

  • 149.

  • 150.

  • 151.

  • 152.

  • 153.

  • 154.

  • 155.

  • 156.

  • 157.

  • 158.

  • 159.

  • 160.

  • 161.

  • 162.

  • 163.

  • 164.

  • 165.

  • 166.

  • 167.

  • 168.

  • 169.

  • 170.

  • 171.

  • 172.

  • 173.

  • 174.

  • 175.

  • 176.

  • 177.

  • 178.

  • 179.

  • 180.

  • 181.

  • 182.

  • 183.

  • 184.

  • 185.

  • 186.

  • 187.

  • 188.

  • 189.

  • 190.

  • 191.

  • 192.

  • 193.

  • 194.

  • 195.

  • 196.

  • 197.

  • 198.

  • 199.

  • 200.

  • 201.

  • 202.

  • 203.

  • 204.

  • 205.

  • 206.

  • 207.

  • 208.

  • 209.

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表示。

21    2016-08-15 13:34:37    React Native iOS js入口