【編者按】本篇文章的做者是 Joyce Echessa——渥合數位服務創辦人,畢業於臺灣大學,近年來專一於協助客戶進行 App 軟體以及網站開發。本篇文章中,做者介紹經過 React Native 框架構建一個示例應用的開發過程,使得網絡技術和移動開發碰撞出絢麗火花,本文系 OneAPM 工程師編譯整理:javascript
咱們已經瞭解像 Titanium 和 PhoneGap 等框架,它們能讓開發者用 Web 技術構建移動應用。這是一個優點,支持開發者使用原先網絡和移動開發的相關技術。不只如此,相同的代碼庫通過小幅度的修改便能適用多個平臺——這就是著名的「一次編寫,處處運行」。然而,當涉及到構建應用的性能時,這些框架的缺點顯露無遺,儘管它們有一些吸引力,但卻一直更適用於構建原生應用。html
React Native 卻不同凡響。像 PhoneGap 這樣的框架是將網頁內容包裝成 WebView,致使 UI 元素並無原生的感受,而 React Native 則使用原生 iOS 或 Android 組件支持的 JavaScript 組件,因此你構建的應用是徹底原生的。java
Facebook 的湯姆 Occhino 在文章末尾連接視頻中說,React Native 並不是是「一次編寫,處處運行」的框架。正如本教程所介紹,你使用特定平臺的組件來構造 UI,因此並不能直接將一樣的代碼放到 Android 上運行。React Native 是讓你學習這套技能,並能夠用它在多種平臺上搭建應用,Occhino 更進一步闡明,這實際上是「一次編寫,處處運行」的框架。在本文中,做者將介紹利用 React Native 框架構建一個簡單應用的完整開發過程。node
首先,介紹一下在開發機器上安裝 React Native 的流程。react
開始以前,應該提醒你們:你能夠從 GitHub 獲取 React Native 框架代碼。接着運行其中的示例項目,好比2048(遊戲)、Movies (電影瀏覽器應用)、SampleApp(空白的 React Native 應用)、TicTacToe (遊戲)和 UIExplorer(這個應用展示了全部可能用到的 React Native 組件,好比 ListView、TabBar、MapView、Slider 等)。這些應用能幫助你學習使用 React Native 構建 UI 元素,尤爲是 UIExplorer 應用程序,它提供了你可能須要用到的每一個 UI 元素。可是,有些應用程序還有 Bug,筆者在嘗試運行時也出現過幾回崩潰。儘管如此,它們仍然很是值得學習,如需詳情,你能夠了解下相關文檔。ios
如今開始安裝。React native 利用 Node.js 來搭建 JavaScript 代碼。若是你電腦上已經安裝過,則能夠跳過如下步驟,不然請繼續如下步驟。git
咱們選擇使用 Homebrew 來安裝 Node.js 框架。雖然這不是安裝 Node 的惟一方式,但我發現,Homebrew 是很是好用的包管理器。你能夠用它很容易地安裝最新或特定版本的包、使用不一樣版本的軟件包、選擇要使用的版本、更新和卸載包等。想要安裝 Homebrew,能夠直接去官網,按照網頁頁面頂部指令便可。因爲連接可能會變,這裏就不貼出下載連接了。github
在 Homebrew 安裝好後,粘貼如下指令到終端窗口以安裝 Node.js。npm
brew install node
接着安裝 watchman。swift
brew install watchman
Watchman 是 Facebook 的文件監控器。React Native 用它來檢測代碼變化,以便從新編譯。
接着用下列指令安裝 React Native CLI 工具。
npm install -g react-native-cli
NPM 是 Node 的包管理器。你能夠將它想象成 Ruby 中的 RubyGems、iOS 的 CocoaPods,以及 Java 中的 Gradle/Maven 等。它可以讓你更容易地下載和管理項目所需的任何相關項。
在終端窗口,切換到你想要保存項目的文件夾,而後運行如下命令。
react-native init BookSearch
以上是用 CLI 工具來構建一個能夠編譯和運行的 React Native 項目。當這個過程完成後,你會收到來自終端窗口的消息,在 Xcode 中打開 BookSearch.xcodeproj,並照常運行該應用程序。接下來模擬器將啓動你的應用,此外,將再打開一個終端窗口。當一個 React Native 應用啓動時,它將從如下網址加載 JavaScript 程序。
http://localhost:8081/index.ios.bundle
終端窗口打開後,會啓動 React Packager,並由服務器處理以上請求。React Packager 負責讀取並構建 JSX(以後會介紹)和 JavaScript 代碼。
運行應用時,你會看到下圖的模擬器。若是你要在設備上運行,應該按照如下幾個步驟。
順便說一句,你應該注意歡迎界面給出的關鍵指令:經過編輯建立項目時生成的 index.ios.js 文件,編輯應用的用戶界面,若是你修改了 JavaScript 代碼,用 Command-R 加載應用程序,看看有什麼變化。若是你想要更多選擇,使用 Command-Control-Z 打開開發者功能表,它提供啓用時從新加載、瀏覽器調試等選項。
當你按照本文操做,模擬器上卻忽然出現一個紅色屏幕時,不妨檢查一下模擬器上的錯誤消息。經過檢查能夠排查出問題是出自代碼仍是服務器。做者也曾經遇到幾回服務器鏈接失敗的狀況,由模擬器反饋的錯誤消息是「沒法鏈接到服務器」,然而檢查終端時獲得「進程終止」的錯誤消息。面對這種狀況時,須要關閉終端窗口,中止在 Xcode 上的應用,並從新運行。對於其餘錯誤好比代碼中的語法錯誤、網絡請求超時錯誤(若是你的應用是從網絡獲取數據),在修正錯誤後再從新加載應該就能夠了。
若是在鍵盤上按下 Command-R 沒什麼用,那麼鍵盤可能沒能鏈接到模擬器。從模擬器功能表中選擇硬件>鍵盤>鏈接硬件鍵盤,便能成功鏈接。
若是你已經完成以上步驟,卻仍沒有從新加載,那麼可能須要從新啓動計算機。筆者曾經遇到過一次奇葩經歷,項目運行一切正常,但卻忽然中止工做,從新啓動後又恢復正常。
如今開始構建咱們的應用。打開 index.ios.js 文件。做者推薦使用適用於 Web 開發的 IDE。固然你也可使用 Xcode,但不久你會發現它並非很適合。當你須要代碼格式化時,它的用處不大,沒法自動填充或語法錯誤高亮。對於適合的 JavaScriptIDE,你能夠通讀本文後再作決定。我用的是 RubyMine,事實上只要是支持 JavaScript 的任何 IDE 都行,若是你選擇一個還能支持 JSX 的那會更好。
當打開 index.ios.js 文件時,你會發現這些代碼構建的是執行應用時所看到的 UI。
'use strict';
上述代碼開啓了 Strict Mode,這將爲 React Native 中的 JavaScript 代碼加入了改良的錯誤處理能力。
var React = require('react-native');
上述代碼載入 react-native 模塊,並將其分配給 React 變量。在你能夠調用模塊的全部功能以前,必須加載外部模塊到項目文件。就像在 Swift 和 Objective-C 中導入庫。
var { AppRegistry, StyleSheet, Text, View, } = React;
以上代碼被稱做解構賦值,可以讓你分配多個對象屬性到一個單變量。使得這些屬性能夠在整個文件範圍中引用。以上代碼是可選的,但若是你省略不要,那麼每當你在代碼中使用一個組件時,你必須使用其完整名稱,例如「React.AppRegistry」、「React.StyleSheet」而不是 「AppRegistry」、「StyleSheet」。
var BookSearch = React.createClass({ render: function() { return ( <View style={styles.container}> <Text style={styles.welcome}> Welcome to React Native! </Text> <Text style={styles.instructions}> To get started, edit index.ios.js </Text> <Text style={styles.instructions}> Press Cmd+R to reload,{'\n'} Cmd+Control+Z for dev menu </Text> </View> ); } });
上面代碼建立了只有單一函數 render()的類。不管 render 中定義了什麼,都將被輸出到屏幕。上述代碼使用 JSX(JavaScript 語法擴展)來構建應用的用戶界面。若是你以前已經使用 XML(甚至 HTML),那麼對 JSX 應該不陌生。它一樣須要使用開始、結束標記,在標記中使用屬性來設置數值。React Native 沒必要非得使用 JSX,你能夠用普通的 JavaScript,但筆者更推薦 JSX,由於它簡化了定義的樹結構的過程。若是你須要大量的代碼構建 UI,經過龐大的 JSX 樹結構使代碼可讀性更強。
var 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, }, });
以上代碼是應用於視圖內容的樣式。若是你之前作過網絡開發,並且使用過 CSS(層疊樣式表),那麼這應該很熟悉。React Native 使用 CSS 設定應用的用戶界面。再看一眼 JSX 代碼,你會發現每一個樣式都各有用途,例如 style={} styles.container 爲容器定義樣式,容器是用來容納其餘 UI 組件的外部視圖。
AppRegistry.registerComponent('BookSearch', () => BookSearch);
上行代碼定義了應用的入口。也就是 JavaScript 代碼開始執行的地方。
這是 React Native 用戶界面的基礎結構。每一個定義的視圖將會遵循這一基礎結構。
在本篇文章中,咱們將建立一個示例應用,能夠瀏覽書籍,並看到詳細信息好比做者、標題、該書簡介。你也能夠在應用中搜索書名和做者。下圖是該應用的成品圖,數據用的是 Google 書籍 API。
示例應用將有兩個項目的標籤欄——精選和搜索。咱們首先添加該功能。
雖然你能夠在 index.ios.js 中編寫全部代碼,但這種作法並不推薦,隨着應用代碼量的增長,整個框架容易變得混亂不堪。爲了更便於管理,咱們在不一樣的文件中建立類。
在項目中根目錄中建立兩個 JavaScript 文件(與 index.ios.js 文件在相同位置)。命名這兩個文件爲 Search.js 和 Featured.js。打開 Featured.js 並添加如下代碼。
'use strict'; var React = require('react-native'); var { StyleSheet, View, Text, Component } = React; var styles = StyleSheet.create({ description: { fontSize: 20, backgroundColor: 'white' }, container: { flex: 1, justifyContent: 'center', alignItems: 'center' } }); class Featured extends Component { render() { return ( <View style={styles.container}> <Text style={styles.description}> Featured Tab </Text> </View> ); } } module.exports = Featured;
這段代碼你應該很是熟悉,很是相似於咱們前面的代碼。咱們設置 Strict Mode、加載 react-native 模塊、建立視圖樣式並用 render()函數渲染輸出到用戶界面。代碼的最後一行輸出精選類,從而使其可用於其餘文件。請注意,咱們聲明類和函數的方式,略微不一樣於示例 inindex.ios.js 文件。JavaScript 有不一樣的聲明類和函數的方式。隨意選擇你喜歡的風格。本篇文章接下來,咱們將一直沿用上面所使用的樣式。
在樣式表定義中,咱們能夠看到基本的 CSS 屬性。咱們爲外部視圖中的文本和中心內容,設置字體大小和背景顏色。但你可能不熟悉 flex: 1
這行,這是最近才增長到 CSS 規範中的 flexbox。這裏的 flex: 1
使得標記爲容器的元素只佔用的屏幕中的剩餘空間,也就是隻佔用適應其內容的足夠空間。以後咱們會進一步介紹 Flex。要了解更多關於 Flexbox 樣式,你能夠參考這個指南。
在 Search.js 中添加下面代碼。
'use strict'; var React = require('react-native'); var { StyleSheet, View, Text, Component } = React; var styles = StyleSheet.create({ description: { fontSize: 20, backgroundColor: 'white' }, container: { flex: 1, justifyContent: 'center', alignItems: 'center' } }); class Search extends Component { render() { return ( <View style={styles.container}> <Text style={styles.description}> Search Tab </Text> </View> ); } } module.exports = Search;
上面的代碼與 Featured.js 的代碼很像,除了文本控件中的文字。
刪除 index.ios.js 中的全部內容,將下面的代碼粘貼進去。
'use strict'; var React = require('react-native'); var Featured = require('./Featured'); var Search = require('./Search'); var { AppRegistry, TabBarIOS, Component } = React; class BookSearch extends Component { constructor(props) { super(props); this.state = { selectedTab: 'featured' }; } render() { return ( <TabBarIOS selectedTab={this.state.selectedTab}> <TabBarIOS.Item selected={this.state.selectedTab === 'featured'} icon={{uri:'featured'}} onPress={() => { this.setState({ selectedTab: 'featured' }); }}> <Featured/> </TabBarIOS.Item> <TabBarIOS.Item selected={this.state.selectedTab === 'search'} icon={{uri:'search'}} onPress={() => { this.setState({ selectedTab: 'search' }); }}> <Search/> </TabBarIOS.Item> </TabBarIOS> ); } } AppRegistry.registerComponent('BookSearch', () => BookSearch);
此時,咱們須要以前建立文件中導出的兩個模塊,並將它們分配給變量。在類中,咱們指定一個構造函數,用來設置類的狀態。所使用的組件均有狀態變量,而後建立一個名爲 selectedTab 的屬性,並將其值賦給「featured」。咱們將利用「featured」來肯定選項卡是否有效。最後爲 Featured 標籤設定默認值。(未完待續...)
敬請持續關注:《React Native 簡介:用 JavaScript 搭建 iOS 應用》系列(2)(3).