【編者按】本篇文章的作者是 Joyce Echessa——渥合數(shù)位服務(wù)創(chuàng)辦人,畢業(yè)于臺灣大學(xué)炎咖,近年來專注于協(xié)助客戶進(jìn)行 App 軟體以及網(wǎng)站開發(fā)翩瓜。本篇文章中酱固,作者介紹通過 React Native 框架構(gòu)建一個示例應(yīng)用的開發(fā)過程,使得網(wǎng)絡(luò)技術(shù)和移動開發(fā)碰撞出絢麗火花蒸健,本文系 OneAPM 工程師編譯整理:
我們已經(jīng)了解像 Titanium 和 PhoneGap 等框架座享,它們能讓開發(fā)者用 Web 技術(shù)構(gòu)建移動應(yīng)用。這是一個優(yōu)勢似忧,支持開發(fā)者使用原先網(wǎng)絡(luò)和移動開發(fā)的相關(guān)技術(shù)渣叛。不僅如此,相同的代碼庫經(jīng)過小幅度的修改便能適用多個平臺——這就是著名的「一次編寫盯捌,到處運(yùn)行」淳衙。然而,當(dāng)涉及到構(gòu)建應(yīng)用的性能時,這些框架的缺點(diǎn)顯露無遺箫攀,盡管它們有一些吸引力肠牲,但卻一直更適用于構(gòu)建原生應(yīng)用。

React Native 卻與眾不同靴跛。像 PhoneGap 這樣的框架是將網(wǎng)頁內(nèi)容包裝成 WebView缀雳,導(dǎo)致 UI 元素并沒有原生的感覺,而 React Native 則使用原生 iOS 或 Android 組件支持的 JavaScript 組件梢睛,所以你構(gòu)建的應(yīng)用是完全原生的肥印。
Facebook 的湯姆 Occhino 在文章末尾鏈接視頻中說,React Native 并非是「一次編寫绝葡,到處運(yùn)行」的框架深碱。正如本教程所介紹,你使用特定平臺的組件來構(gòu)造 UI挤牛,所以并不能直接將同樣的代碼放到 Android 上運(yùn)行莹痢。React Native 是讓你學(xué)習(xí)這套技能,并可以用它在多種平臺上搭建應(yīng)用墓赴,Occhino 更進(jìn)一步闡明竞膳,這其實(shí)是「一次編寫,到處運(yùn)行」的框架诫硕。在本文中坦辟,作者將介紹利用 React Native 框架構(gòu)建一個簡單應(yīng)用的完整開發(fā)過程。
開始吧章办!
首先锉走,介紹一下在開發(fā)機(jī)器上安裝 React Native 的流程。
開始之前藕届,應(yīng)該提醒大家:你可以從 GitHub 獲取 React Native 框架代碼挪蹭。接著運(yùn)行其中的示例項(xiàng)目,比如2048(游戲)休偶、Movies (電影瀏覽器應(yīng)用)梁厉、SampleApp(空白的 React Native 應(yīng)用)、TicTacToe (游戲)和 UIExplorer(這個應(yīng)用展現(xiàn)了所有可能用到的 React Native 組件踏兜,比如 ListView词顾、TabBar、MapView碱妆、Slider 等)肉盹。這些應(yīng)用能幫助你學(xué)習(xí)使用 React Native 構(gòu)建 UI 元素,尤其是 UIExplorer 應(yīng)用程序疹尾,它提供了你可能需要用到的每個 UI 元素上忍。但是骤肛,有些應(yīng)用程序還有 Bug,筆者在嘗試運(yùn)行時也出現(xiàn)過幾次崩潰窍蓝。盡管如此萌衬,它們?nèi)匀环浅V档脤W(xué)習(xí),如需詳情它抱,你可以了解下相關(guān)文檔秕豫。
現(xiàn)在開始安裝。React native 利用 Node.js 來搭建 JavaScript 代碼观蓄。如果你電腦上已經(jīng)安裝過混移,則可以跳過以下步驟,否則請繼續(xù)以下步驟侮穿。
我們選擇使用 Homebrew 來安裝 Node.js 框架歌径。雖然這不是安裝 Node 的唯一方式,但我發(fā)現(xiàn)亲茅,Homebrew 是非常好用的包管理器回铛。你可以用它很容易地安裝最新或特定版本的包、使用不同版本的軟件包克锣、選擇要使用的版本茵肃、更新和卸載包等。想要安裝 Homebrew袭祟,可以直接去官網(wǎng)验残,按照網(wǎng)頁頁面頂部指令即可。由于鏈接可能會變巾乳,這里就不貼出下載鏈接了您没。
在 Homebrew 安裝好后,粘貼以下指令到終端窗口以安裝 Node.js胆绊。
brew install node
接著安裝 watchman氨鹏。
brew install watchman
Watchman 是 Facebook 的文件監(jiān)控器。React Native 用它來檢測代碼變化压状,以便重新編譯仆抵。
接著用下列指令安裝 React Native CLI 工具。
npm install -g react-native-cli
NPM 是 Node 的包管理器何缓。你可以將它想象成 Ruby 中的 RubyGems肢础、iOS 的 CocoaPods还栓,以及 Java 中的 Gradle/Maven 等碌廓。它能夠讓你更容易地下載和管理項(xiàng)目所需的任何相關(guān)項(xiàng)。
在終端窗口剩盒,切換到你想要保存項(xiàng)目的文件夾谷婆,然后運(yùn)行以下命令。
react-native init BookSearch
以上是用 CLI 工具來構(gòu)建一個可以編譯和運(yùn)行的 React Native 項(xiàng)目。當(dāng)這個過程完成后纪挎,你會收到來自終端窗口的消息期贫,在 Xcode 中打開 BookSearch.xcodeproj,并照常運(yùn)行該應(yīng)用程序异袄。接下來模擬器將啟動你的應(yīng)用通砍,此外,將再打開一個終端窗口烤蜕。當(dāng)一個 React Native 應(yīng)用啟動時封孙,它將從以下網(wǎng)址加載 JavaScript 程序。
http://localhost:8081/index.ios.bundle
終端窗口打開后讽营,會啟動 React Packager虎忌,并由服務(wù)器處理以上請求。React Packager 負(fù)責(zé)讀取并構(gòu)建 JSX(之后會介紹)和 JavaScript 代碼橱鹏。

運(yùn)行應(yīng)用時膜蠢,你會看到下圖的模擬器咧擂。如果你要在設(shè)備上運(yùn)行抡砂,應(yīng)該按照以下幾個步驟。

順便說一句铝条,你應(yīng)該注意歡迎界面給出的關(guān)鍵指令:通過編輯創(chuàng)建項(xiàng)目時生成的 index.ios.js 文件糖荒,編輯應(yīng)用的用戶界面贪惹,如果你修改了 JavaScript 代碼,用 Command-R 加載應(yīng)用程序寂嘉,看看有什么變化奏瞬。如果你想要更多選擇,使用 Command-Control-Z 打開開發(fā)者功能表泉孩,它提供啟用時重新加載硼端、瀏覽器調(diào)試等選項(xiàng)。

當(dāng)你按照本文操作寓搬,模擬器上卻突然出現(xiàn)一個紅色屏幕時珍昨,不妨檢查一下模擬器上的錯誤消息。通過檢查可以排查出問題是出自代碼還是服務(wù)器句喷。作者也曾經(jīng)遇到幾次服務(wù)器連接失敗的情況镣典,由模擬器反饋的錯誤消息是「無法連接到服務(wù)器」,然而檢查終端時得到「進(jìn)程終止」的錯誤消息唾琼。面對這種情況時兄春,需要關(guān)閉終端窗口,停止在 Xcode 上的應(yīng)用锡溯,并重新運(yùn)行赶舆。對于其他錯誤比如代碼中的語法錯誤哑姚、網(wǎng)絡(luò)請求超時錯誤(如果你的應(yīng)用是從網(wǎng)絡(luò)獲取數(shù)據(jù)),在修正錯誤后再重新加載應(yīng)該就可以了芜茵。
如果在鍵盤上按下 Command-R 沒什么用叙量,那么鍵盤可能沒能連接到模擬器。從模擬器功能表中選擇硬件>鍵盤>連接硬件鍵盤九串,便能成功連接绞佩。
如果你已經(jīng)完成以上步驟,卻仍沒有重新加載猪钮,那么可能需要重新啟動計(jì)算機(jī)征炼。筆者曾經(jīng)遇到過一次奇葩經(jīng)歷,項(xiàng)目運(yùn)行一切正常躬贡,但卻突然停止工作谆奥,重新啟動后又恢復(fù)正常。
現(xiàn)在開始構(gòu)建我們的應(yīng)用拂玻。打開 index.ios.js 文件酸些。作者推薦使用適用于 Web 開發(fā)的 IDE。當(dāng)然你也可以使用 Xcode檐蚜,但不久你會發(fā)現(xiàn)它并不是很適合魄懂。當(dāng)你需要代碼格式化時,它的用處不大闯第,無法自動填充或語法錯誤高亮市栗。對于適合的 JavaScriptIDE,你可以通讀本文后再做決定咳短。我用的是 RubyMine填帽,事實(shí)上只要是支持 JavaScript 的任何 IDE 都行,如果你選擇一個還能支持 JSX 的那會更好咙好。
當(dāng)打開 index.ios.js 文件時篡腌,你會發(fā)現(xiàn)這些代碼構(gòu)建的是執(zhí)行應(yīng)用時所看到的 UI。
'use strict';
上述代碼開啟了 Strict Mode勾效,這將為 React Native 中的 JavaScript 代碼加入了改良的錯誤處理能力嘹悼。
var React = require('react-native');
上述代碼載入 react-native 模塊,并將其分配給 React 變量层宫。在你可以調(diào)用模塊的所有功能之前杨伙,必須加載外部模塊到項(xiàng)目文件。就像在 Swift 和 Objective-C 中導(dǎo)入庫萌腿。
var {
AppRegistry,
StyleSheet,
Text,
View,
} = React;
以上代碼被稱作解構(gòu)賦值限匣,能夠讓你分配多個對象屬性到一個單變量。使得這些屬性可以在整個文件范圍中引用哮奇。以上代碼是可選的膛腐,但如果你省略不要,那么每當(dāng)你在代碼中使用一個組件時鼎俘,你必須使用其完整名稱哲身,例如「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>
);
}
});
上面代碼創(chuàng)建了只有單一函數(shù) render()的類。無論 render 中定義了什么捉邢,都將被輸出到屏幕脯丝。上述代碼使用 JSX(JavaScript 語法擴(kuò)展)來構(gòu)建應(yīng)用的用戶界面。如果你之前已經(jīng)使用 XML(甚至 HTML)伏伐,那么對 JSX 應(yīng)該不陌生宠进。它同樣需要使用開始、結(jié)束標(biāo)記藐翎,在標(biāo)記中使用屬性來設(shè)置數(shù)值材蹬。React Native 不必非得使用 JSX,你可以用普通的 JavaScript吝镣,但筆者更推薦 JSX堤器,因?yàn)樗喕硕x的樹結(jié)構(gòu)的過程。如果你需要大量的代碼構(gòu)建 UI末贾,通過龐大的 JSX 樹結(jié)構(gòu)使代碼可讀性更強(qiáng)闸溃。
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,
},
});
以上代碼是應(yīng)用于視圖內(nèi)容的樣式。如果你以前做過網(wǎng)絡(luò)開發(fā)拱撵,而且使用過 CSS(層疊樣式表)辉川,那么這應(yīng)該很熟悉。React Native 使用 CSS 設(shè)定應(yīng)用的用戶界面拴测。再看一眼 JSX 代碼员串,你會發(fā)現(xiàn)每個樣式都各有用途,例如 style={} styles.container 為容器定義樣式昼扛,容器是用來容納其他 UI 組件的外部視圖寸齐。
AppRegistry.registerComponent('BookSearch', () => BookSearch);
上行代碼定義了應(yīng)用的入口。也就是 JavaScript 代碼開始執(zhí)行的地方抄谐。
這是 React Native 用戶界面的基礎(chǔ)結(jié)構(gòu)渺鹦。每個定義的視圖將會遵循這一基礎(chǔ)結(jié)構(gòu)。
在本篇文章中蛹含,我們將創(chuàng)建一個示例應(yīng)用毅厚,可以瀏覽書籍,并看到詳細(xì)信息比如作者浦箱、標(biāo)題吸耿、該書簡介祠锣。你也可以在應(yīng)用中搜索書名和作者。下圖是該應(yīng)用的成品圖咽安,數(shù)據(jù)用的是 Google 書籍 API伴网。

添加標(biāo)簽欄
示例應(yīng)用將有兩個項(xiàng)目的標(biāo)簽欄——精選和搜索。我們首先添加該功能妆棒。
雖然你可以在 index.ios.js 中編寫所有代碼澡腾,但這種做法并不推薦,隨著應(yīng)用代碼量的增加糕珊,整個框架容易變得混亂不堪动分。為了更便于管理,我們在不同的文件中創(chuàng)建類红选。
在項(xiàng)目中根目錄中創(chuàng)建兩個 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;
這段代碼你應(yīng)該非常熟悉玛瘸,非常類似于我們前面的代碼。我們設(shè)置 Strict Mode苟蹈、加載 react-native 模塊糊渊、創(chuàng)建視圖樣式并用 render()函數(shù)渲染輸出到用戶界面。代碼的最后一行輸出精選類慧脱,從而使其可用于其他文件渺绒。請注意,我們聲明類和函數(shù)的方式菱鸥,略微不同于示例 inindex.ios.js 文件宗兼。JavaScript 有不同的聲明類和函數(shù)的方式。隨意選擇你喜歡的風(fēng)格氮采。本篇文章接下來殷绍,我們將一直沿用上面所使用的樣式。
在樣式表定義中鹊漠,我們可以看到基本的 CSS 屬性主到。我們?yōu)橥獠恳晥D中的文本和中心內(nèi)容,設(shè)置字體大小和背景顏色躯概。但你可能不熟悉 flex: 1
這行登钥,這是最近才增加到 CSS 規(guī)范中的 flexbox。這里的 flex: 1
使得標(biāo)記為容器的元素只占用的屏幕中的剩余空間娶靡,也就是只占用適應(yīng)其內(nèi)容的足夠空間牧牢。之后我們會進(jìn)一步介紹 Flex。要了解更多關(guān)于 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 中的所有內(nèi)容腔寡,將下面的代碼粘貼進(jìn)去。
'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);
此時蜡感,我們需要之前創(chuàng)建文件中導(dǎo)出的兩個模塊蹬蚁,并將它們分配給變量恃泪。在類中郑兴,我們指定一個構(gòu)造函數(shù),用來設(shè)置類的狀態(tài)贝乎。所使用的組件均有狀態(tài)變量情连,然后創(chuàng)建一個名為 selectedTab 的屬性,并將其值賦給「featured」览效。我們將利用「featured」來確定選項(xiàng)卡是否有效却舀。最后為 Featured 標(biāo)簽設(shè)定默認(rèn)值。(未完待續(xù)...)
敬請持續(xù)關(guān)注:《React Native 簡介:用 JavaScript 搭建 iOS 應(yīng)用》系列(2)(3).
原文地址:http://www.appcoda.com/react-native-introduction/
OneAPM 是應(yīng)用性能管理領(lǐng)域的新興領(lǐng)軍企業(yè)锤灿,能幫助企業(yè)用戶和開發(fā)者輕松實(shí)現(xiàn):緩慢的程序代碼和 SQL 語句的實(shí)時抓取挽拔。想閱讀更多技術(shù)文章,請?jiān)L問 OneAPM 官方博客但校。