神刀安全网

Get started系列- React Native

Get started系列- React Native

ReactJS 提供了一种前段开发的新模式,而React Native更是在这个基础上将Web和Mobile两个领域的开发无缝地衔接了在一起。如果你是一名web开发者,而对移动端开发感兴趣的话,不妨通过这篇文章来入门吧。

Facebook 在 React.js Conf 2015 大会上推出了基于 JavaScript 的开源框架 React Native 。用这个框架,我们就可以用Javascript开发原生iOS程序了(安卓版现已发布)!3月底,Facebook已经放出了官方 repository

我们都在用JS和HTML5写App,然后用PhoneGap包好发布到iOS(和安卓)了。 React Native真的好用么?

React Native还真就是那么好用。程序猿都为此兴奋无比,主要有以下两个原因:

  1. 用了React Native, 你的程序尽管用JavaScript写,UI却是本地的,因此无需承受HTML5的UI带来的用户体验损失。
  2. React 有特别的构建用户界面的技巧,使得界面成为一个叙述软件工作状态的交流窗口。

关键是,React Native是要把React的编程方式带到移动端App开发中。和Java的“开发一次,到处使用”的谎言不同,React主张“学习一次,到处开发”,至少比较现实。本教程暂时只讨论iOS,但是你看完以后,一定也知道在安卓上怎么用了。

如果你只用Objective-C或者Swift开发程序,可能你不会对用JavaScript开发程序有想法。但是作为Swift的开发者,多一门手艺并不是坏事。

用过Swift的你,一定掌握了更为有效和规范的算法,更好的控制程序的稳定性和可移植性。但实际上,构建UI的方法和Objective-C并没有多大区别:还是在用UIKit而且别无选择。

而我们的React引入了虚拟DOM的概念,将功能性(甚至面向对象)直接带到了UI开发中来。

本教程中,咱们来做一个搜索英国房产并生成列表的软件。

Get started系列- React Native

如果你没用过JavaScript也没关系,本会会详解代码。React 用CSS属性来管理样式,很简单,当然如果你有需要的话可以专门去学习一下。

好,我们开始吧。

起步

React Native框架就在 GitHub 上,你可以克隆一个项目,也可以下载一个zip文件。如果并不想看源代码,也可以用命令行来创建一个React Native项目。本教程中,咱们就这么做。

React使用Node.js,来构建JavaScript代码。如果没有的话需要装上。

先安装Homebrew(本机使用的是MAC,应该不用解释了),然后命令行安装Node.js

brew install node

再安装 watchman ,Facebook的一款文件监控程序。

brew install watchman

有了这个React Native就可以监察文件的变化并重建。就好比每次保存都用Xcode来build一次。

接下来就可以用npm安装 React Native CLI(命令行工具)。

npm install -g react-native-cli

这就用Node的包管理工具在全局安装了CLI。这方面npm有点像CocoaPods 或者Carthage。

创建一个项目目录,然后进入这个目录:

react-native init PropertyFinder

这就创建了一个叫做PropertyFinder(找房产)的初始项目,里面包含了构建和运行 React Native 程序所需的所有内容。

进入这个目录,你会找到一个node_modules文件夹,这里面放着React Native框架。

同时还会找到一个 index.ios.js文件,这就是CLI创建的程序文件的骨架。

最后,还会看到一个Xcode项目文件和iOS目录,包含了启动程序必须的相关文件。

下面我们build和运行一下这个程序:

Get started系列- React Native

同时我们会注意到一个窗口跳出来:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

这是React Native的包管理程序,在Node下面运行,咱们就知道这是干什么的了。

不要关掉这个窗口,让它在后台自己运行。如果不小心关掉了,重新运行Xcode项目就行。

注意:我们等一下要写大量的JavaScript代码,最好选一个轻量级的编辑器,推荐Sublime Text,当然你自己可以在网上找找。

Hello React Native

在做房产搜索App之前,咱们先做一个Hello World程序。我们在这里会接触到很多重要的组件。

在编辑器中打开index.ios.js,删掉全部内容,然后写下这么一行:

'use strict';

启用Strict模式可以增强JavaScript的除错能力并关掉一些不好的功能。

Note: 了解更多JavaScript的strict模式,请参考 Jon Resig’s article “ECMAScript 5 Strict Mode, JSON, and More”.

然后加上下面这行:

var React = require('react-native');

这就把React Native组件调用起来,并赋予React变量。其中require功能和Node.js是一样的。

Note: 关于JavaScript的模块化组织方式,请参考 this article by Addy Osmani on writing modular JavaScript.

接下来,加上下面这些:

var styles = React.StyleSheet.create({   text: {     color: 'black',     backgroundColor: 'white',     fontSize: 30,     margin: 80   } }); 

这段代码添加了文字的样式。如果你干过web开发,你一定知道这就是CSS。

好了,下面真的是app程序了。

class PropertyFinderApp extends React.Component {   render() {     return React.createElement(React.Text, {style: styles.text}, "Hello World!");   } }

看到了吗?一个JavaScript类(Class)!

类从ECMAScript 6 (ES6)被引入JavaScript。由于JavaScript不断在改进,web开发人员经常因为浏览器兼容性(万恶的IE)而不得不放弃一些功能。React Native有一个JavaScriptCore,因此无需为浏览器兼容性操心。

Note: 如果你是web开发者,我建议先从新的JavaScript标准出发,然后使用 Babel 之类的工具兼容旧版浏览器

PropertyFinderApp 继承 React.Component,React UI的基础模块。Component(组件)包含了不可变的property(属性变量),可变的state(状态变量),并提供一个render(渲染)方法。

React Native 组件不是UIKit类,而是轻量级的。框架会将React组件树转换为本地UI。

最后我们加上这行:

React.AppRegistry.registerComponent('PropertyFinder',  function() { return PropertyFinderApp });

AppRegistry 定义了程序的入口变量,并提供了根组件。

保存好 index.ios.js ,返回Xcode,确认把 PropertyFinder 加进iPhone模拟器,我们重建并运行一下项目。

Get started系列- React Native

这可是本地UI,没有任何浏览器,代码全是JavaScript写的哦!

还是不信?:)打开Xcode的 Debug/View Debugging/Capture View Hierarchy ,是不是哪都找不到 UIWebView ,只有一个真正的View!牛啊。

Get started系列- React Native

你一定很好奇是怎么回事。在Xcode中找到 application:didFinishLaunchingWithOptions: ,这个方法创建了一个 RCTRootView ,来载入JavaScript并渲染了View。

程序一运行, RCTRootView 立刻读取:

brew install watchman

0

来加载程序。

现在知道前面弹出来那个窗口是干什么的了吧,就是处理这个东西的。

程序启动时,代码会载入JavaScriptCore 框架并执行。在这个程序中, PropertyFinderApp 这个component会被加载并创建一个本地的UIKit视图。后面会详细讲到。

Hello JSX

我们现在的程序使用 React.createElement 创建,然后React转换为本地文件。尽管目前我们的js文件很清楚,但随着代码更复杂,各种元素的嵌套会导致代码一团乱麻。

在app继续运行的情况下,我们回到 index.ios.js ,把return改一改:

brew install watchman

1

这是JSX代码,全称叫做JavaScript syntax extension,使用类似HTML的标签。如果是web开发者,一看就懂。我们全程会大量使用JSX代码。

保存文件返回模拟器,按下Cmd+R,我们可以看到“Hello World (again)”,看到没,重新加载React Native程序就跟刷新一下网页一样简单。

由于我们的程序使用的是同一套JavaScript文件,以后只需要修改 index.ios.js 并保存,就可以实现内容的调整。

好了,玩够了Hello World,我们来做真正的程序吧。

添加导航控制

我们的寻找房产程序使用和UIKit类似的栈形导航。下面来做这个导航。

index.ios.js 中,我们把 PropertyFinderApp 重命名为HelloWorld。

brew install watchman

2

Hello World还是会显示,不过已经不是咱们的根组件了。

我们在下面加一点真货:

brew install watchman

3

这样就添加了一个导航控制器,使用了原本HellowWorld组件的路径和样式。在web开发时,routing(路由或路径)被用来设计程序的导航结构,根据URL来分配页面。

然后我们要调整样式:

brew install watchman

4

回到Xcode再刷新一次。

Get started系列- React Native

好了现在我们有了导航框架,可以开始在里面做UI了。

构建搜索页面

我们创建一个新文件 SearchPage.js ,和 index.ios.js 放在一起。添加如下代码:

brew install watchman

5

前面就不说了,下面那个变量声明你可能没有见过。

这叫做 destructuring assignment (解构化赋值),可以把对象的多个属性赋给相应变量。于是,之后你就不必使用React这个前缀,比如你可以直接调用 StyleSheet 而不是 React.StyleSheet 。它还可以用来操作数组,非常好用。

我们还要添加样式:

brew install watchman

6

虽然用css没有Interface Builder那么可视化,但比用 viewDidLoad() 一个一个设置视图属性可方便多了。:)

下面来写组件:

brew install watchman

7

render 可以完美应用JSX的结构。用css我们很容易就实现了这个图形界面:一个容器和两条label。

最后加上:

brew install watchman

8

这条命令制定了输出 SearchPage 以为他用。

下一步就是路由(Routing)的制作。

打开 index.ios.js ,并且在require下面加上这行:

brew install watchman

9

PropertyFinderApp 的render里面替换 initialRoute

npm install -g react-native-cli

0

现在可以干掉Hello World这种新手用的东西了,现在我们是高手了。

回模拟器我们刷新一下Cmd + R:

Get started系列- React Native

这就是我们的新组件,搜索页 SearchPage

用Flexbox来布局

现在,我们用css调整了margin、padding和颜色,不过你可能对flexbox并不熟悉,这是最近出现的新规范,用来做app的UI布局再好不过了。

React Native用的是 css-layout 库,是flexbox标准的一种javascript实现,可以转化为C(iOS)和Java(安卓)。

在App中,默认的排列是依据column(列),所以,子元素默认是垂直排列的。

Get started系列- React Native

这个被叫做主轴(main axis),可以竖着也可以横着。

每个子元素的垂直位置由margin、height和padding决定。容器同时将 alignItems 设置为 center ,所以文档是居中的。

好了,现在要加上input和button了。打开 SearchPage.js 并将下面这段插入到第二段text元素后面:

npm install -g react-native-cli

1

npm install -g react-native-cli

2

现在我们有两个顶级视图了,一个有一个输入框和按钮,一个只有按钮。

下面我们把样式加进style里面:

npm install -g react-native-cli

3

每项属性中用“,”隔开。这些就是输入框和按钮的样式。

我们会模拟器刷新一下 Cmd + R。

Get started系列- React Native

输入框和Go按钮在同一行,因为把它们放在了 flexDirection: ‘row’ 的容器中。我们并没有明确声明它们的宽度,而是给了一个flex值。输入框 flex: 4 ,而按钮则是  flex: 1 ,所以它们的宽度比为4:1.

你可能已经注意到,这个按钮……并不是按钮。在UIKit中,按钮只不过是可以点击的Label,所以React Native团队决定直接用JavaScript构建按钮。程序中的按钮使用 TouchableHighlight 这个组件,使得按钮按下时显示透明和不同的颜色。

最后我们添上一些图片。 可以在这里下载 。在Xcode中,打开  Images.xcassets ,点击加号添加图片。接下来鼠标拖动图片到相应的格子。

Get started系列- React Native

这次需要停掉程序并重启,来让图片加载出现。

将下面这行添加到location按钮 TouchableHighlight 组件的下面:

npm install -g react-native-cli

4

下面添加图片的样式:

npm install -g react-native-cli

5

上面的 require('image!house') 是为了获取图片的位置。在Xcode中,如果打开 Images.xcassets 的话,我们会找到房屋图标。

返回模拟器刷新一下页面,Cmd + R。

Get started系列- React Native

注意:如果看不到图片而显示“image!house”的话,重启包管理器(或者命令行npm start)

添加组件state(状态参数)

每一个React组件都有其state状态参数,用来储存关键变量。组件初始化之前要先初始化state。

SearchPage.js 中,在render()上面添加如下代码:

npm install -g react-native-cli

6

我们的组件现在有了一个state变量,名为searchString值为’london’。

然后就可以使用组件的状态了。在Render中,改变TextInput如下代码:

npm install -g react-native-cli

7

我们把输入框的值——也就是用户看到的那个——和我们的state值 searchString 绑定起来了。

好了,值是初始化好了,但是,当用户输入时,会发生什么呢?(自己去试试)

我们要绑定一个事件,在 SearchPage 中添加如下方法:

npm install -g react-native-cli

8

这样,系统就会取出输入框的值并且替换state的值。

下面要把这个方法串进输入框中,要将函数绑定到onChange属性上:

npm install -g react-native-cli

9

这样每次用户在输入框中输入,都会触动onChange,并执行 onSearchTextChanged

注意:如果不明白bind(this)方法是干什么的,JavaScript处理this关键字与其他语言不太一样,用Swift翻译就是self。用bind是为了确保this指向组件实例。可以自己去试试就明白了。

最后,把下面这些记录函数添加到render中,return上面:

react-native init PropertyFinder

0

这样我们就会明白一些非常神奇的东西。

现在刷新一下程序。我们应该可以看到界面中的”london”,并且在命令行中,我们看到:

Get started系列- React Native

嗯……顺序似乎有点问题。

  1. 首次启动render
  2. 当输入框有变化,启动 onSearchTextChanged()
  3. 更新state,并引发另一次render
  4. onSearchTextChanged() 并装入新的搜索内容

每次任何state发生变化,React组件会将整个UI全部重新render一遍,这是好的,这就解耦了state与UI状态。

在其他的UI框架中,要么你手动更改UI的内容,要么进行双向绑定,比如某些MVVM模式的框架。

在React中,你无需担心哪块UI绑到什么地方,整个UI都是state的一个体现。

看到这里,你可能已经发现这个模式的缺点了——性能问题!

我们总不能每次state有点改动,就把整个UI全部扔掉,然后重新加载吧?好了React在这个问题上相当智能化。每次UI渲染时,都会把render方法返回的视图树,拿去与现存的UIKit视图树作对比。于是对比的结果,就是需要更改的视图树。所以只有改变了的部分需要重新渲染。

看到这里我是非常佩服React.js的虚拟DOM给iOS带来的如此特别的合作方式。

我们把上面那些日志方法全部删掉,下面我们开始完善程序。

启动搜索功能

要实现搜索功能,我们要处理Go按钮的按下事件,并发出API请求,同时视觉上告诉用户请求正在进行。

SearchPage.js 中,更改初始化state:

react-native init PropertyFinder

1

在render中增加如下内容:

react-native init PropertyFinder

2

根据isLoading这个state是否为真,显示活动视图或空视图。

在搜索UI的return中,在 Image 下面,增加:

react-native init PropertyFinder

3

把下面这个属性加到Go按钮的渲染方法中的 TouchableHighlight 标签里:

react-native init PropertyFinder

4

然后在 SearchPage 类中加入以下方法:

react-native init PropertyFinder

5

现在的_executeQuery只是写一条日志,将来会完善的。

注意: JavaScript的类没有私有前缀,所以前面加个_来表示私有。

当Go按钮按下时,程序会执行 onSearchPressed() ,启动查询。

最后,在searchPage类的声明上加上这个工具函数:

react-native init PropertyFinder

6

这个函数和searchPage没有依赖,所以作为一个独立函数,而不作为类的方法。这个函数先用一个data来储存参数,然后构建查询请求。其中,=>这是个新语法,(参数)=>{函数体}。

回到模拟器,按下Cmd + R刷新,点击Go,就会看到滚动图标,然后我们看看后台。

Get started系列- React Native

我们会看到url,复制下来贴进浏览器,我们来看看结果,会看到一大段JSON内容。现在还不用管这些。

注意:本教程使用了 Nestoria API  来获取房产信息。相关细节可以参考网站文档。

下一步,就是在App内发起请求了。

发起API请求

还是在 SearchPage.js ,添加一个message变量。

react-native init PropertyFinder

7

在render中,在底部添加一行:

react-native init PropertyFinder

8

这个可以用来显示信息给用户看。

SearchPage 中,添加以下代码到 _executeQuery() 中:

react-native init PropertyFinder

9

这里用到了fetch方法,来自Web API,提供了一个比XMLHttpRequest更好的API接口。异步回应返回一个promise,带来目标路径以及JSON文档。

最后我们来处理返回的文档,把这段加在SearchPage里面:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

0

拿掉了isLoading并且做了日志记录。

保存起来,然后回模拟器Cmd + R。我们搜索london,应该会看到20条记录在日志里面。然后试一下随便输一个’ narnia’,你会看到如下情况:

Get started系列- React Native

显示结果

创建一个 SearchResults.js ,并添加代码如下:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

1

这一段,看是很眼熟吧?

然后是组件本身:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

2

上面的代码用了一个 ListView 组件,用于在可滚动的容器内添加多行内容,有点像UITableView。数据的来源是 ListView.DataSource

构建数据源时,需要提供一个函数来对比一对数据。ListView在组建的过程中会调用这个函数,用于编制列表。这次的回传数据中,Nestoria API提供 guid ,就刚好适合这个目的。

别忘了添加输出模块代码:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

3

讲一下这段添加到 SearchPage.js 中,require下面:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

4

这样我们就可以在 SearchPage 中调用 SearchResults 了。

编辑 _handleResponse 方法:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

5

上面的代码导向 SearchResults 页面,并且将结果列表传进去。用push方法将搜索结果传入导航,这样就可以用回退功能返回之前页面。

返回模拟器并Cmd + R,你会看到列表:

Get started系列- React Native

当然,这是看不得的,太丑了。

妙手生花

React Native 对你来说应该比较熟了,我们就加快脚步。

将代码加到 SearchResults.js :中的结构化定义下面:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

6

然后把 renderRow() 替换成下面这些

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

7

这次,图片使用URL,React Native会负责从主线程中解析。而且rowData.grid使用=>方法来获取。

最后一步是处理按下:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

8

刷新一下,我们可以看到:

Get started系列- React Native

看起来很不错。但是,这个房价根本没人买的起吧。

我们准备将最后一个视图做出来

房产详情视图

新建一个 PropertyView.js ,然后添加以下代码:

===============================================================   |  Running packager on port 8081.          |  Keep this packager running while developing on any JS            |  projects. Feel free to close this tab and run your own         |  packager instance if you prefer.                                 |                                                                 |     https://github.com/facebook/react-native                    |                                                                 ===============================================================   Looking for JS files in     /Users/colineberhardt/Temp/TestProject   React packager ready.

9

现在,你睡着了都应该写的出来。

然后是样式:

'use strict';

0

接着是组件:

'use strict';

1

render的第一部分对数据做了一些处理,因为很多情况下数据是不完整的。

最后别忘了输出:

'use strict';

2

回到 SearchResults.js ,增加一个require,你懂的:

'use strict';

3

改一下 rowPressed() 来实现 PropertyView 的导航。

'use strict';

4

刷新一下,你也懂的。

Get started系列- React Native

最后一步:让用户搜索附近的房子。

基于地理位置的搜索

在Xcode中,打开 Info.plist 并添加新key,右键点击编辑期内并选择 Add Row NSLocationWhenInUseUsageDescription 作为键名,以下作为键值:

'use strict';

5

以下是完成的plist :

Get started系列- React Native

打开 SearchPage.js ,找到渲染“Location”那个按钮的 TouchableHighlight ,并且加上下列:.

'use strict';

6

当你点击按钮,就会触发 onLocationPressed

打开 SearchPage ,添加:

'use strict';

7

获取现在位置的方法是 navigator.geolocation ,这是Web API,React有自己的一套实现,用的是iOS原生的位置服务。

如果成功获取现在的位置,系统会向Nestoria拉取数据,如果失败,就会显示错误信息。

由于改变了plist,这次我们就不能Cmd +R了。重新建立工程并启动吧。

在启动位置搜索服务前,我们必须指定一处Nestoria 数据库覆盖的地方。作为测试,我们在模拟器中选择 Debug/Location/Custom Location 输入北纬55.02,经度 -1.42 ,这是北英格兰一处安静的港口。

Get started系列- React Native

附:React-Native学习指南

React Native

深入浅出系列教程

React.js

ES6

React Native探索系列教程

开源APP

转载自: http://1ke.co/course/269

原作: React Native Tutorial: Building Apps with JavaScript

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Get started系列- React Native

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮