React Native新手引导

序言

本教程希望让您快速熟悉使用React Native来编写iOS和Android App的技巧。如果你希望知道React Native是什么以及为什么Facebook打造了它,可以读读这篇博文

我们这里假设你已经有了使用React编写Web应用程序的经验。如果还没有,建议你可以先从React官网开始学习。

准备工作

React Native需要一些基础的配置工作,你可以参考开始使用React Native来进行。

在所有依赖的软件都已经安装完毕后,只需要输入两条命令就可以创建一个React Native工程。

  1. npm install -g react-native-cli

    react-native-cli是一个终端命令,它可以完成其余的设置工作。它可以通过npm安装。刚才这条命令会往你的终端安装一个叫做react-native的命令。这个安装过程你只需要进行一次。

  2. react-native init AwesomeProject

    这个命令会初始化一个工程、下载React Native的所有源代码和依赖包,最后在AwesomePrjoect/iOS/AwesomeProject.xcodeprojAwesomeProject/android/app下分别创建一个新的XCode工程和一个gradle工程。 

译注:由于众所周知的网络原因,react-native命令行从npm官方源拖代码时会遇上麻烦。请先将npm仓库源替换为国内镜像: 

npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist

另,执行init时切记不要在前面加上sudo(否则新项目的目录所有者会变为root而不是当前用户,导致一系列权限问题,请使用chown修复)。
本站论坛区提供了完整的绿色纯净新项目包。完整打包全部iOS和Android的第三方依赖,只要环境配置正确,无需科学上网漫长等待,解压即可直接运行。

开发

想开发iOS版本,你现在可以在XCode中打开刚刚创建的工程(AwesomePrjoect/iOS/AwesomeProject.xcodeproj),然后只要按下?+R就可以构建并运行。这个操作会同时打开一个用于实现动态代码加载的Node服务(React Packager)。所以每当你修改代码,你只需要在模拟器中按下?+R,而无需重新在XCode中编译。

想开发Android版本,先连接你的设备或启动模拟器,然后在AwesomeProject目录下运行react-native run-android,就会构建工程并自动安装到你的模拟器或者设备,同时启动用于实现动态代码加载的Node服务。当你修改代码之后,你需要打开摇一摇菜单(摇一下设备,或者按下设备的Menu键,或者在模拟器上按下F2或Page Up,Genymotion按下?+M),然后在菜单中点击“Reload JS”。

在本向导中我们会创建一个简单的Movies应用,它可以获取25个上映中的电影,然后把他们在一个ListView中显示。

Hello World

react-native init命令会创建一个指定名字的应用,我们刚才输入的命令就创建了一个名为AwesomePrjoect的应用。这是一个简单的Hello World应用。对于iOS版本,你可以编辑index.ios.js来做一些改动,然后在模拟器中按?+R来看到修改的结果。对Android版本,你可以编辑index.android.js来做一些改动,然后在摇一摇菜单中点击“Reload JS”来看到修改的结果。

模拟数据

译注:本文的示例代码改用了ES6语法,可能和其他文档写法不一致。但React Native从0.18之后,新建项目默认已经采用了ES6语法,故我们推荐不熟悉ES6与ES5区别的朋友先读读这篇文章,另外还可以看看阮一峰老师的书。

在我们真正从Rotten Tomatoes(译注:一个国外的电影社区)抓取数据之前,我们先制造一些模拟数据来练一练手。在Facebook我们通常在JS文件的开头,紧跟着import语句之后声明一个常量,不过这不重要,你可以把它放在index.ios.jsindex.android.js的任意位置:

var MOCKED_MOVIES_DATA = [{title: '标题', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}},
];

展现一个电影

我们接下来要展现一个电影,绘制它的标题、年份、以及缩略图(译注:这个过程我们通常会叫做“渲染/render”,后面我们都会用“渲染”这个词)。渲染缩略图需要用到Image组件,所以把Image添加到对React的import列表中。

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

然后修改一下render函数,这样我们可以把上面创建的模拟数据渲染出来。

  render() {var movie = MOCKED_MOVIES_DATA[0];return (<View style={styles.container}><Text>{movie.title}</Text><Text>{movie.year}</Text><Image source={{uri: movie.posters.thumbnail}} /></View>);}

按下?+R或者Reload JS,现在你应该能看到文字"Title"和"2015",但现在Image组件没渲染任何东西,这是因为我们还没有为图片指定我们想要渲染的宽和高。这通过样式来实现。当我们修改样式的时候,我们也应该清理掉我们不再使用的样式。

var styles = StyleSheet.create({container: {flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},thumbnail: {width: 53,height: 81,},
});

然后把它应用到Image组件上:

        <Imagesource={{uri: movie.posters.thumbnail}}style={styles.thumbnail}/>

按下?+R或者Reload JS,现在图片应该可以被渲染出来了。

  

添加样式

现在我们已经成功的把我们的数据渲染出来了,下面让我们把它弄的更好看一些。我想把文字放在图片的右边,然后把标题弄的大一些,并且水平居中:

+---------------------------------+
|+-------++----------------------+|
||       ||        标题          ||
|| 图片  ||                      ||
||       ||        年份          ||
|+-------++----------------------+|
+---------------------------------+

所以我们需要增加一个container来实现一个水平布局内嵌套一个垂直布局。

      return (<View style={styles.container}><Imagesource={{uri: movie.posters.thumbnail}}style={styles.thumbnail}/><View style={styles.rightContainer}><Text style={styles.title}>{movie.title}</Text><Text style={styles.year}>{movie.year}</Text></View></View>);

和之前相比并没有太多变化,我们增加了一个container来包装文字,然后把它移到了Image的后面(因为他们最终在图片的右边)。然后我们来看看样式要怎么改:

  container: {flex: 1,flexDirection: 'row',justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},

我们用Flexbox来布局。如果你想了解更多,可以读读这篇文章。

在上面的代码片段中,我们用了一句flexDirection: 'row'来让我们的主容器的成员从左到右横向布局,而非默认的从上到下纵向布局。

现在我们往style对象里增加另一个样式:

  rightContainer: {flex: 1,},

这句话的作用是让rightContainer在父容器中占据Image之外剩下的全部空间。如果你还不是很理解的话,你可以往rightContainer里增加一个backgroundColor看一看,然后再去掉flex:1对比一下。你会发现去掉这一句后,容器会变成能容纳它孩子的最小大小。

给文字添加样式就简单的多了:

  title: {fontSize: 20,marginBottom: 8,textAlign: 'center',},year: {textAlign: 'center',},

再按一次?+R或者Reload JS来看看最新的结果。

  

拉取真正的数据

从Rotten Tomatoes的API拉取数据和学习React Native并没有什么直接关系,所以你也可以直接跳过本节。

把下面的常量放到文件的最开头(通常在require下面)来创建我们请求数据所需的地址常量REQUEST_URL

/*** 为了避免骚扰,我们用了一个样例数据来替代Rotten Tomatoes的API* 请求,这个样例数据放在React Native的Github库中。*/
var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';

首先在应用中创建一个初始的null状态,这样可以通过this.state.movies == null来判断我们的数据是不是已经被抓取到了。我们在服务器响应返回的时候执行this.setState({movies: moviesData})来改变这个状态。把下面这段代码放到我们的React类的render函数之前:

  constructor(props) {super(props);   //这一句不能省略,照抄即可this.state = {movies: null,  //这里放你自己定义的state变量及初始值};}

组件加载完毕之后,就可以向服务器请求数据。componentDidMount是React组件的一个生命周期方法,它会在组件刚加载完成的时候调用一次,以后不再会被调用。React中的各种生命周期方法请参阅此文档。

  componentDidMount() {this.fetchData();}

现在我们来为组件添加fetchData函数。你所需要做的就是在Promise调用链结束后执行this.setState({movies:data})。在React的工作机制下,setState实际上会触发一次重新渲染的流程,此时render函数被触发,发现this.state.movies不再是null。注意我们在Promise调用链的最后调用了done() —— 这样可以抛出异常而不是简单忽略。

  fetchData() {fetch(REQUEST_URL).then((response) => response.json()).then((responseData) => {this.setState({movies: responseData.movies,});}).done();}

现在我们来修改render函数。在电影数据加载完毕之前,先渲染一个“加载中”的视图;而如果电影数据已经加载完毕了,则渲染第一个电影数据。

  render() {if (!this.state.movies) {return this.renderLoadingView();}var movie = this.state.movies[0];return this.renderMovie(movie);}renderLoadingView() {return (<View style={styles.container}><Text>正在加载电影数据……</Text></View>);}renderMovie(movie) {return (<View style={styles.container}><Imagesource={{uri: movie.posters.thumbnail}}style={styles.thumbnail}/><View style={styles.rightContainer}><Text style={styles.title}>{movie.title}</Text><Text style={styles.year}>{movie.year}</Text></View></View>);}

现在再按一次?+R或者Reload JS,你会首先看到“正在加载电影数据……”,然后在响应数据到达之后,看到第一个电影的信息。

  

ListView

现在我们来让我们的应用能够渲染所有的数据而不是仅仅第一部电影。我们要用到的就是ListView组件。

为什么建议把内容放到ListView里?比起直接渲染出所有的元素,或是放到一个ScrollView里有什么优势?这是因为尽管React很高效,渲染一个可能很大的元素列表还是会很慢。ListView会安排视图的渲染,只显示当前在屏幕上的那些元素。而那些已经渲染好了但移动到了屏幕之外的元素,则会从原生视图结构中移除(以提高性能)。

首先要做的事情:在文件最开头,从React中引入ListView

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

现在来修改render函数。当我们已经有了数据之后,渲染一个包含多个电影信息的ListView,而不仅仅是单个的电影。

  render() {if (!this.state.loaded) {return this.renderLoadingView();}return (<ListViewdataSource={this.state.dataSource}renderRow={this.renderMovie}style={styles.listView}/>);}

dataSource接口用来在ListView的整个更新过程中判断哪些数据行发生了变化。

你会注意到我们现在用到了this.state中的dataSource。下一步就是在constructor生成的初始状态中添加一个空白的dataSource。另外,我们现在要把数据存储在dataSource中了,所以不再另外用this.state.movies来保存数据。我们可以在state里用一个布尔型的属性(this.state.loaded)来判断数据加载是否已经完成了。

  constructor(props) {super(props);this.state = {dataSource: new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2,}),loaded: false,};}

同时我们也要修改fetchData方法来把数据更新到dataSource里:

  fetchData() {fetch(REQUEST_URL).then((response) => response.json()).then((responseData) => {this.setState({dataSource: this.state.dataSource.cloneWithRows(responseData.movies),loaded: true,});}).done();}

最后,我们再在styles对象里给ListView添加一些样式。

  listView: {paddingTop: 20,backgroundColor: '#F5FCFF',},

现在可以体现最终的结果了:

  

为了实现一个完整功能的应用,接下来其实还有一些工作要做,譬如:添加导航器,搜索,加载更多,等等等等。可以在Movies示例中看看我们做了什么。

最终的代码

/*** Sample React Native App* https://github.com/facebook/react-native*/import React, {AppRegistry,Component,Image,ListView,StyleSheet,Text,View,
} from 'react-native';var API_KEY = '7waqfqbprs7pajbz28mqf6vz';
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json';
var PAGE_SIZE = 25;
var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE;
var REQUEST_URL = API_URL + PARAMS;class AwesomeProject extends Component {constructor(props) {super(props);this.state = {dataSource: new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2,}),loaded: false,};}componentDidMount() {this.fetchData();}fetchData() {fetch(REQUEST_URL).then((response) => response.json()).then((responseData) => {this.setState({dataSource: this.state.dataSource.cloneWithRows(responseData.movies),loaded: true,});}).done();}render() {if (!this.state.loaded) {return this.renderLoadingView();}return (<ListViewdataSource={this.state.dataSource}renderRow={this.renderMovie}style={styles.listView}/>);}renderLoadingView() {return (<View style={styles.container}><Text>Loading movies...</Text></View>);}renderMovie(movie) {return (<View style={styles.container}><Imagesource={{uri: movie.posters.thumbnail}}style={styles.thumbnail}/><View style={styles.rightContainer}><Text style={styles.title}>{movie.title}</Text><Text style={styles.year}>{movie.year}</Text></View></View>);}
};var styles = StyleSheet.create({container: {flex: 1,flexDirection: 'row',justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},rightContainer: {flex: 1,},title: {fontSize: 20,marginBottom: 8,textAlign: 'center',},year: {textAlign: 'center',},thumbnail: {width: 53,height: 81,},listView: {paddingTop: 20,backgroundColor: '#F5FCFF',},
});AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

本文转自React Native中文网:http://reactnative.cn/docs/0.20/tutorial.html#content

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/500030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[设计模式] ------ 代理模式

几句话讲明白代理模式 静态代理&#xff1a; 1.定义 个接口A,接口有个方法methodA(); 2.定义一个实现类B,实现这个接口A,并重写方法methodA(); 3.定义一个代理类C,也实现接口A,并将类B作为他的一个属性&#xff0c; 然后C也重写方法methodA();但方法的实现为B&#xff0c;并调…

React Native使用指南-原生模块

有时候App需要访问平台API&#xff0c;但React Native可能还没有相应的模块封装&#xff1b;或者你需要复用Objective-C、Swift或C代码&#xff0c;而不是用JavaScript重新实现一遍&#xff1b;又或者你需要实现某些高性能、多线程的代码&#xff0c;譬如图片处理、数据库、或者…

服务器启动报错:One or more listeners failed to start. Full details will be found in the ...

idea本地启动web项目时 报错如下: One or more listeners failed to start. Full details will be found in the appropriate container log file 我的解决方案: 增加一步,配置artifacts 具体如下: 这个地方选择自己本地的web项目文件夹 都配置完然后Apply下,这个都配置好…

React Native使用指南-原生UI组件

在如今的App中&#xff0c;已经有成千上万的原生UI部件了——其中的一些是平台的一部分&#xff0c;另一些可能来自于一些第三方库&#xff0c;而且可能你自己还收藏了很多。React Native已经封装了大部分最常见的组件&#xff0c;譬如ScrollView和TextInput&#xff0c;但不可…

[网络]------长连接和短连接

本文重点介绍&#xff1a; 长连接和短连接的定义&#xff0c;优缺点以及使用场景 前提须知: 1.HTTP/1.0默认使用短连接,HTTP/1.1开始,默认使用长连接 2.HTTP协议的长连接和短连接,实质是就是TCP协议的长连接和短连接 3.tcp协议建立连接需要三次握手,这个过程会耗费网络资源…

React Native使用指南-使用链接库

并不是所有的APP都需要使用全部的原生功能&#xff0c;包含支持全部特性的代码会增大应用的体积。但我们仍然希望能让你简单地根据自己的需求添加需要的特性。 在这种思想下&#xff0c;我们把许多特性都发布成为互不相关的静态库。 大部分的库只需要拖进两个文件就可以使用了&…

[网络]------TCP UDP HTTP Socket 区别

关于这几个的概念,网上已经很全面了,在这个做个笔记: 前提须知: 1.协议就是大家提前约定的一种规范,后人照着这个遵循就可以,也可以将语言理解为一种协议 2.网络通信的世界中,有七层协议(应用层,表示层,会话层,传输层,网络层,数据链路层,物理层) 正题: 1.TCP和UDP都属于传…

React Native使用指南-在设备上运行

注意在iOS设备上运行React Native应用需要一个Apple Developer account并且把你的设备注册为测试设备。本向导只包含React Native相关的主题。 译注&#xff1a;从XCode 7起&#xff0c;在自己的设备上调试App不再需要开发者账户了。 从设备访问开发服务器 在启用开发服务器的情…

java 贪吃蛇游戏

前言 此实现较为简陋&#xff0c;如有错误请指正。 其次代码中的图片需要自行添加地址并修改。 主类 public class Main { public static void main(String[] args) { new myGame(); } } 1 2 3 4 5 游戏类 import javax.swing.*; import java.awt.eve…

java方向好看的书

从Lucene到ElasticSearch:全文检索实战 大数据架构详解&#xff1a;从数据获取到深度学习 代码整洁之道 架构解密&#xff1a;从分布式到微服务 从Paxos到Zookeeper分布式一致性原理与实践 大型网站技术架构 核心原理与案例分析 分布式服务架构&#xff1a;原理、设计与实…

React Native使用指南-植入原生应用

由于React并没有假设你其余部分的技术栈——它通常只作为MVC模型中的V存在——它也很容易嵌入到一个并非由React Native开发的应用当中。实际上&#xff0c;它可以和常见的许多工具结合&#xff0c;譬如CocoaPods。 需求 CocoaPods – gem install cocoapodsNode.js 安装 nvm&a…

[数据库]---nosql,非关系型数据库整理

1.关系型数据库与非关系型数据库的区别 Tables关系型数据库非关系型数据库成本好的收费开源的,都免费的存储与查询硬盘存储,相对查的慢内存存储,查的快存储格式只能是基本格式多种多样年龄出现时间较长,较成熟后起之秀,不可小觑扩展性join等不好扩展方便集群事务强事务弱事务查…

React Native开发指南-在原生和React Native间通信

通过植入原生应用和原生UI组件两篇文档&#xff0c;我们学习了React Native和原生组件的互相整合。在整合的过程中&#xff0c;我们会需要在两个世界间互相通信。有些方法已经在其他的指南中提到了&#xff0c;这篇文章总结了所有可行的技术。 简介 React Native是从React中得到…

数据迁移记录

做数据迁移,数据库是分两片,每片一主两从,没有读写分离 前提: 使用服务器1:2核4G内存40G硬盘 线程池:5个 每个线程分页查询,每页1000条 平均数据是一天一个线程,一天3万数据,所以大概就是30页的分页深度 服务器1的数据: cpu使用率在74%上下(有点高,2核的毕竟比不过4核的…

RPC协议简介

一、概述 1.英文原义&#xff1a;Remote Procedure Call Protocol 2.中文释义&#xff1a;&#xff08;RFC-1831&#xff09;远程调用协议 。 3.注解&#xff1a;一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。 4.说明&#xff1a;RPC…

mysql分页查询报错,及解决

mysql分页查询报错: 前提: 1.每页1000条数据 2.查到57页的时候,就报错了 以下是错误信息: org.springframework.jdbc.UncategorizedSQLException: ### Error querying database. Cause: java.sql.SQLException: ...省略中间... received message larger than max (1844105…

RPC协议与Web Service

一、引入 我们每天都在使用浏览器来上网冲浪, 在查找自己需要的资源, HTTP协议自然是我们使用的最多的 一种, 我们尽情地享受着这种信息高速路的快感,却没有试图去了解我们是如何获得这些资源的? 它是一种什么样的设计理念? 我们也偶尔会使用 Gtalk来和自己的同事或者朋友来聊…

如何设置电脑开机自动提示(防止忘打卡等)

如何设置电脑开机自动提示: 第一种方法: 第一步:CtrlR 输入mmc命令打开 文件-添加/删除管理单元-组策略对象编辑器-添加-确定-确定(都是默认的)。 第二步:退出小框,会看见有个”本地计算机 策略”,打开-计算机配置-windows设置-安全设置-本地策略-安全选项 双击”交互式登…

RestFull架构

1 什么是REST REST全称是Representational State Transfer&#xff0c;中文意思是表述性状态转移。 它首次出现在2000年Roy Fielding的博士论文中&#xff0c;Roy Fielding是 HTTP 规范的主要编写者之一。 他在论文中提到:“我这篇文章的写作目的&#xff0c;就是想在符合架构原…

SpringMVC默认访问路径配置

SpringMVC默认访问路径配置 需求:只访问域名,不加任何action路径,想访问默认的一个action. 比如www.jd.com,就跳到京东首页,会加载出辣么多东西来 关于这个的方法,网上有千千万种,在这里只是记录一种常用的, 亲测这个可以用,而且我们的项目一直都是这个套路. 第一步,web.x…