React Native窄驹,是一個(gè)混合移動(dòng)應(yīng)用開發(fā)框架蝙茶,本文根據(jù) By C. Enrique Ortiz 的文章 Dissecting React Native 同時(shí)結(jié)合自己開發(fā)中的一些理解編寫
React Native 是目前流行的跨平臺(tái)移動(dòng)應(yīng)用開發(fā)框架之一酣栈。本文概述了 React Native,以及作者在開發(fā) React Native 應(yīng)用的最佳實(shí)踐經(jīng)驗(yàn)雜談。
在開發(fā)移動(dòng)應(yīng)用時(shí),我們可以選擇使用原生祟牲,純基于 Web 或使用混合方法(即使用原生和基于 Web 的技術(shù)的組合)《恫浚可以使用 Apache Cordova(或 Adobe PhoneGap)等開源平臺(tái)編寫 HTML说贝,CSS 和 JavaScript 的跨平臺(tái)混合應(yīng)用。這些應(yīng)用在原生 Web 視圖(瀏覽器)中運(yùn)行慎颗,所以看著就像 Web 應(yīng)用乡恕,不過可以使用 JavaScript 和一些 Apache Cordova 插件調(diào)用原生功能和 API换淆。所以可以使用類似于 Web 應(yīng)用而非原生應(yīng)用的用戶界面上架到 Apple Store 或 Google Play 的應(yīng)用〖秆眨或者,可以使用 C#讯屈,XAML 和 CSS 使用 Xamarin 來編寫原生應(yīng)用蛋哭。對(duì)于用 HTML5,CSS 和 JavaScript 編寫的非原生移動(dòng) Web 應(yīng)用涮母,還可以配套使用 jQuery Mobile 等框架谆趾。
React Native 采用不同的方法進(jìn)行混合移動(dòng)應(yīng)用開發(fā)。它不會(huì)生成原生 UI 組件叛本,而是基于 React沪蓬,React Native 是一個(gè)用于構(gòu)建基于 Web 的交互界面的 JavaScript 庫,因此會(huì)有更豐富的 UI 體驗(yàn)效果来候,同時(shí)也能夠很好地調(diào)用底層框架的UI使用跷叉。 React Native 已經(jīng)成為一種流行的移動(dòng)開發(fā)技術(shù),它提供了一個(gè)使用 JavaScript 構(gòu)建原生跨平臺(tái)移動(dòng)應(yīng)用的強(qiáng)大框架营搅,在需要時(shí)云挟,我們也可以使用 Objective-C,Swift或 Java 來編寫原生代碼來橋接转质。
使用 React Native 有利有弊园欣。從積極的方面來說,React Native 已經(jīng)成為受支持的開源社區(qū)的熱門休蟹,可以使用一組技術(shù)(如 JSX沸枯,React Native 組件和 JavaScript)為 iOS 和 Android 構(gòu)建移動(dòng)應(yīng)用。這反過來有助于在發(fā)布新版本時(shí)使 iOS 和 Android 應(yīng)用保持同步赂弓。但是绑榴,React Native 仍在不斷發(fā)展,當(dāng)要在當(dāng)前不需要 React Native 提供的功能(例如如何進(jìn)行UI導(dǎo)航或使用地圖)時(shí)決定使用哪些庫時(shí)盈魁,可能會(huì)造成混淆彭沼。此外,根據(jù)應(yīng)用的復(fù)雜程度备埃,可能需要編寫區(qū)別于平臺(tái)的代碼來解決移動(dòng)平臺(tái)的差異姓惑。對(duì)于復(fù)雜的應(yīng)用,可能要編寫自定義組件或深入了解 iOS 和 Android(例如按脚,出于性能原因或?qū)?React Native 添加到現(xiàn)有原生應(yīng)用時(shí)所需的但不支持的UI組件)于毙。
配置 React Native 環(huán)境
React Native 的核心語言是 JavaScript,特別是 ECMAScript 6(ES6)辅搬。因此唯沮,需要熟悉ES6的一些最新功能脖旱。此外,在開始開發(fā)第一個(gè) React Native 應(yīng)用之前介蛉,需要安裝必備的工具萌庆,比如 IDE,JavaScript 庫等币旧。另外践险,還需要了解核心的 React Native API。
ECMAScript 6 功能
ES6 引入了許多改進(jìn)吹菱,其中一些值得一提巍虫,因?yàn)樗鼈冊(cè)谧钚碌?React Native 框架中已經(jīng)被用到:
- 變量和作用域:關(guān)鍵字 var,let 和 const 表示變量作用域鳍刷,其中 var 是函數(shù)作用域占遥,let 是塊作用域,const 也是塊作用域输瓜。 const 變量是常量瓦胎,但在 JavaScript 中對(duì)于對(duì)象和數(shù)組來說,它是可變的尤揣。解釋器將變量聲明提升或移動(dòng)到var 聲明的作用域頂部凛捏,而 let 和 const 聲明不會(huì)被掛起。
- 箭頭函數(shù):一種新類型的函數(shù)芹缔,它允許更緊湊坯癣,更簡(jiǎn)潔的表示法,并且具有靜態(tài)或詞匯的定義(它不會(huì)在詞法上圍繞它)最欠∈韭蓿可以看以下這些示例。
沒有指定參數(shù)的箭頭函數(shù):
() => { ... }
帶一個(gè)參數(shù)芝硬,注意省略了的括號(hào):
x => { ... }
指定幾個(gè)參數(shù):
(x, y) => {*
...
}
參數(shù)定義和箭頭函數(shù)的箭頭必須在同一行中蚜点。
- Promises:Promises 是異步編程的替代API,它提供了優(yōu)于傳統(tǒng)回調(diào)(如鏈接和并行執(zhí)行)的優(yōu)勢(shì)拌阴。
function myAsyncFunc() {
return new Promise(
function (resolve, reject) {
:
resolve(result);
:
if (error) {
reject(error);
}
});
}
比較以前的異步函數(shù):
myAsyncFunc().then(result =\> { ··· }).catch(error =\> { ··· });
這只是新功能的一個(gè)示例绍绘,但還有許多其他功能。關(guān)于ES6的一個(gè)很好的在線參考是 Axel Rauschmayer 的 Exploring ES6迟赃。
接下來陪拘,我們來看看如何設(shè)置開發(fā)平臺(tái)和環(huán)境。
設(shè)置環(huán)境和工程
目前來看纤壁,開發(fā) iOS 原生應(yīng)用只能用 macOS 系統(tǒng)左刽。由于大多數(shù)移動(dòng)應(yīng)用都會(huì)涉及到 Android 和 iOS兩端,因此應(yīng)該考慮使用 Mac 來開發(fā) React Native 移動(dòng)應(yīng)用酌媒。
在創(chuàng)建項(xiàng)目之前欠痴,你需要安裝一堆東西迄靠,主要包括:
Android Studio和Xcode工具:安裝最新版本以構(gòu)建和發(fā)布應(yīng)用。對(duì)于 Android 開發(fā)喇辽,確保為要運(yùn)行的Android API 版本配置正確的模擬器掌挚。
JavaScript IDE或文本編輯器:不需要使用 Xcode 或 Android Studio 來編寫 JavaScript 代碼,真正需要的只是一個(gè)文本編輯器菩咨。比如使用 Atom(由 GitHub 開發(fā))吠式,Sublime Text 或喜歡的任何優(yōu)秀文本編輯器,筆者目前用的是 VSC旦委。
-
JavaScript 或 React Native 包:安裝一些工具來管理 React Native 軟件包以及三方庫,包括:
- 從 nodejs.org 下載 node.js:為了讓JavaScript 運(yùn)行時(shí)允許訪問npm雏亚,這是一個(gè)由 node.js 項(xiàng)目創(chuàng)建的便捷工具缨硝,可用于管理開源軟件包。確保下載 node.js 的最新 LTS(長期支持)版本罢低。此下載中還包括一個(gè)名 為 Metro bundler 的開發(fā)服務(wù)器查辩,它在調(diào)試時(shí)能夠提供實(shí)時(shí)更新渲染。
- 下載 create-react-native-app:可以使用此工具開始開發(fā)网持。它可以創(chuàng)建一個(gè)基礎(chǔ)項(xiàng)目宜岛。使用 npm 來下載:
sudo npm install -g create-react-native-app
-
下載常用的第三方庫。 React Nativ 提供了很多基礎(chǔ)組件功舀,與原生 API 使用相比會(huì)更加簡(jiǎn)單萍倡。常規(guī)的移動(dòng)應(yīng)用使用可能包括有相機(jī),管理狀態(tài)辟汰,并具有導(dǎo)航列敲,地圖,圖標(biāo)和復(fù)選框帖汞。這都都可以從 React Native 社區(qū)獲取對(duì)用組件:
- react-native-navigation
- react-native-vector-icons
- redux
- React-native-maps
此外戴而,可以到React Native Elements獲取需要的其他UI組件元素。在開發(fā)一個(gè)完整功能的 app 時(shí)翩蘸,需要用到上面提到的 UI 組件所意。用這個(gè)方法來安裝以前的 packages :
npm install _package-name_ --save
React Native Debugger:這是一個(gè)非常棒的調(diào)試器,同時(shí)它還是一個(gè)獨(dú)立的應(yīng)用催首,里面能用到的工具包括 React Inspector 和 Redux DevTools扶踊。配置好環(huán)境后可以連接到應(yīng)用(注意:一次只能調(diào)適一個(gè)應(yīng)用),可以很方便的實(shí)時(shí)查看 React Native 應(yīng)用的狀態(tài)郎任,調(diào)適必備工具,如圖所示:
現(xiàn)在姻檀,來建立一個(gè)簡(jiǎn)單應(yīng)用并運(yùn)行一下:
1.創(chuàng)建工程。用以下語句來創(chuàng)建涝滴,指定創(chuàng)建的工程路徑绣版,默認(rèn)創(chuàng)建在當(dāng)前路徑下:
create-react-native-app [APPNAME]
cd [APPNAME]
注意:這一步創(chuàng)建了一個(gè)沒有進(jìn)行任何配置的 React Native app 模板胶台。在 GitHub 項(xiàng)目中閱讀有關(guān) create-react-native-app 的更多信息。
安裝完成后杂抽,可以使用 npm 執(zhí)行以下命令來運(yùn)行應(yīng)用:
- npm start 運(yùn)行 app
- npm run ios:跟 npm start 相似诈唬,這是用來運(yùn)行 iOS 應(yīng)用
- npm run android:運(yùn)行 Android 應(yīng)用,如果需要運(yùn)行模擬器缩麸,需要提前打開模擬器
- npm run eject:從當(dāng)前的 create-react-native 模式中彈出 app铸磅,這樣就可以完全控制應(yīng)用構(gòu)建過程(筆者沒用過)
2.啟動(dòng) app。通過運(yùn)行 npm run android 和 npm run ios 在模擬器上運(yùn)行應(yīng)用杭朱。這將在開發(fā)模式下啟動(dòng)應(yīng)用阅仔。同時(shí)還會(huì)啟動(dòng) Metro bundler,可以在修改代碼后實(shí)時(shí)更新應(yīng)用(在調(diào)試移動(dòng)應(yīng)用時(shí)這很棒)弧械。
如果運(yùn)行成功八酒,會(huì)有這樣的提示:
React Native API 概述
我們簡(jiǎn)單快速瀏覽一下 React Native API ,從 React 轉(zhuǎn)變過來的 React Native 刃唐,它繼承了 JSX羞迷,state,props 和組件生命周期的概念画饥。然后衔瓮,它通過提供對(duì)原生UI組件和功能的支持來擴(kuò)展 React。這是通過導(dǎo)入 React 和 React Native 功能來實(shí)現(xiàn)的抖甘,如清單1所示:
清單1.從 React 和 React Native 導(dǎo)入
import React, { Component } from **'react'**
import { View, ScrollView, StyleSheet } from **'react-native**'
導(dǎo)入后热鞍,我們就可以訪問 React Native 對(duì)應(yīng)的組件,這些組件支持我們所需的許多常用UI組件:
- 基礎(chǔ)UI組件:如 View衔彻,Text碍现,Image,TextInput米奸,ScrollView 和 StyleSheet昼接。此外,還提供了UI控件悴晰,如Button慢睡,Picker,Slider 和 Switch铡溪。
- 列表:FlatList(用于呈現(xiàn)可滾動(dòng)列表)和 SectionList(類似于 FlatList 但用于分段列表)的列表
- Android 專用組件:如 Android BackHandler漂辐,DatePickerAndroid,ToastAndroid棕硫。
- iOS 專用組件:如 AlertIOS髓涯,ImagePickerIOS,NavitatorIOS哈扮,TabBarIOS纬纪。
- 通用組件:可以在 Components and APIs 上查詢所有的公共組件蚓再。
還有一點(diǎn)需要注意,React Native 還提供了很多原來不支持的功能包各。比如使用地圖摘仅,甚至是圖標(biāo)和復(fù)選框。雖然底層操作系統(tǒng)支持问畅,但 React Native 還是需要安裝第三方庫娃属。也就是說,React Native(包括開發(fā)工具)所支持的任何復(fù)雜或不受支持的內(nèi)容都要求我們編寫其他代碼或使用第三方庫來承載护姆。
使用 React Native 構(gòu)建應(yīng)用
常規(guī)的的 React Native 應(yīng)用由許多組件組成矾端,如圖所示:
在一個(gè)應(yīng)用容器中,每個(gè)界面會(huì)包含一個(gè)或多個(gè) View(和樣式)卵皂,界面跳轉(zhuǎn)導(dǎo)航秩铆,狀態(tài)管理和數(shù)據(jù)模型。還有本地存儲(chǔ)和網(wǎng)絡(luò)請(qǐng)求功能渐裂。最后但并非最不重要的是豺旬,有很多第三方庫可以擴(kuò)展應(yīng)用的功能钠惩。
以下介紹部分圖中內(nèi)容:
Screens: Views and styles
應(yīng)用容器中包含多個(gè) screen 和其他組件的集合柒凉。應(yīng)用本身由許多 screen 組成,每個(gè) screen 包含多個(gè)視圖篓跛,如按鈕膝捞,文本輸入和列表。View 是構(gòu)建用戶界面的最基本組件愧沟,映射到 iOS 和 Android 的原生 View 組件蔬咬。
清單2是一個(gè)界面示例,包含一個(gè)列表沐寺,使用 ScrollView 實(shí)現(xiàn)林艘,以及一個(gè)封裝在 Checkbox UI 組件中的任務(wù)列表:
# components/TaskList/TaskList.js
import React, { Component } from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import { CheckBox } from 'react-native-elements'
import styles from './TaskListStyle;
export default class TaskList extends Component {
renderTaskItem = (item, idx) => {
return (
<View style={styles.row}>
<Checkbox
checked = {item.checked}
title = {item.text}
onPress = { () => onPressItem(item, idx) }
/>
</View>
);
}
render() {
const {list} = this.props
return (
<ScrollView style={styles.container}>
{list.map( this.renderTaskItem )}
</ScrollView>
)
}
}
代碼中列表組件需要導(dǎo)入各種依賴項(xiàng),包括 React Native 中未找到的第三方Checkbox UI組件混坞,可以從 React Native Elements下載該組件狐援。
在清單2中,UI組件和樣式是分開的究孕。我們可以創(chuàng)建更高級(jí)UI組件并與樣式隔離開啥酱。我們把所有組件放到一個(gè)子目錄中,每個(gè)組件都有其 component.js 和 style.js 文件厨诸,如清單3所示:
./Components
+-TaskList
+-TaskList.js
+-TaskListStyle.js
或者镶殷,使用更通用的方法:
+-TaskList
+-index.js
+-style.js
清單4顯示了一個(gè)樣式文件的示例:
# components/TaskList/TaskListStyle.js
import { StyleSheet } from 'react-native';
// Define the styles
export default StyleSheet.create({
container: {
flex: 1,
paddingLeft: 20,
},
row: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start',
},
});
樣式需要使用 StyleSheet 組件創(chuàng)建,它類似于 CSS 樣式表微酬』媲鳎可以查看 individual UI component 獲取更多樣式屬性颤陶。
自適應(yīng)布局
React Native 提供了一個(gè) Dimensions 組件來檢測(cè)屏幕尺寸:
import { Dimensions } from 'react-native';
var {height, width} = Dimensions.get('window');
Dimensions 可根據(jù)需要實(shí)時(shí)調(diào)整界面UI;例如,我們可以根據(jù)需要的應(yīng)用樣式埋心,在方向更改時(shí)調(diào)整UI指郁,包括改變橫向與縱向方向的文本輸入字段的位置和長度。
另外我們還可能需要處理另一種情況的UI適配拷呆。比如需要實(shí)現(xiàn) Androi d或 iOS 特有的行為的情況闲坎。包括與兩端系統(tǒng)相關(guān)的差異,例如UI控件的呈現(xiàn)及使用茬斧。要解決此設(shè)計(jì)問題腰懂,我們需要使用不同的邏輯或樣式,或者在更復(fù)雜的情況下项秉,實(shí)現(xiàn)自定義組件绣溜。因此 React Native 提供了不同的方法來檢測(cè)系統(tǒng),以便可以以編程方式?jīng)Q定要執(zhí)行的操作:使用 Platform 組件甚至使用特定于平臺(tái)的文件擴(kuò)展名娄蔼。
使用Platform 組件檢測(cè)系統(tǒng)會(huì)返回“ios”或“android”怖喻。例如:
import {Platform} from 'react-native';
if (Platform.OS === 'ios') {
}
if (Platform.OS === 'android') {
}
Platform 還提供 Platform.select 和 Platform.Version,分別用于檢測(cè)平臺(tái)和平臺(tái)版本岁诉。有關(guān)更多信息锚沸,請(qǐng)參閱平臺(tái)文檔。應(yīng)該僅對(duì)較小的更改使用 Platform.O S和 Platform.select涕癣。否則哗蜈,我們將使用大量硬編碼的 if 或 switch 語句,這會(huì)使寫的代碼更難以遵循坠韩。
如果要編寫更復(fù)雜的代碼或組件距潘,則應(yīng)使用特定于平臺(tái)的文件擴(kuò)展名。在這種方法中只搁,使用每個(gè)平臺(tái)文件拆分代碼音比。也就是說,如果我們的代碼不能跨平臺(tái)公用氢惋,比如我們的任務(wù)列表洞翩,那么將編寫兩個(gè)文件,一個(gè)用于 iOS明肮,一個(gè)用于Android菱农,然后讓 React Native 選擇對(duì)應(yīng)的文件:
./Components
+-TaskList
+-TaskList.io.js
+-TaskList.android.js
+-TaskListStyle.ios.js
+-TaskListStyle.android.js
然后,讓React Native選擇正確的文件:
const TaskList = require('./Components/TaskList/TaskList);
本文未介紹 iOS 和 Android 之間究竟有什么不同柿估,但要注意的事項(xiàng)包括渲染和常規(guī)組件或UI控件使用布局⊙矗現(xiàn)在,如果事實(shí)證明 Android 與 iOS 應(yīng)用的布局設(shè)計(jì)在主要方面有所不同,我們可以分別使用 index.ios.js 和 index.android.js 文件而不是 index.js 來控制主應(yīng)用的妖。這就可以完全控制不同平臺(tái)的應(yīng)用布局和流程绣檬。為了最大限度地減少重復(fù)代碼,需要將其重新打包為可重用的程序嫂粟。
導(dǎo)航
React Native 中的導(dǎo)航是一個(gè)具有挑戰(zhàn)性的領(lǐng)域娇未,因?yàn)?React Native 提供的導(dǎo)航要么不夠強(qiáng)大奠支,要么僅針對(duì) iOS絮宁。相反虑啤,有大量社區(qū)項(xiàng)目試圖解決跨平臺(tái)導(dǎo)航問題类嗤,其中一些項(xiàng)目比其他項(xiàng)目更受歡迎。這里只是重點(diǎn)闡述當(dāng)下流行的 React Native Navigation扔枫。
React Native Navigation 提供了一套非常完整的 API 來注冊(cè)界面組件线脚,包括含有 tab 的應(yīng)用嵌赠,以及啟動(dòng)單個(gè)界面應(yīng)用卸亮。同時(shí)它還提供了其他 API 來管理模態(tài)跳轉(zhuǎn)和導(dǎo)航跳轉(zhuǎn)忽妒,以及用于處理堆棧,處理按鈕兼贸,可見性以及自定義導(dǎo)航器本身的低級(jí) API段直。
安裝最新穩(wěn)定版本的 react-native-navigation(運(yùn)行 npm install react-native-navigation --save)并按照其網(wǎng)站上的 Android 和 iOS 安裝說明進(jìn)行操作
另外必須通過調(diào)用 registerComponent()將唯一名稱的 Navigator 注冊(cè)到所有 screen 組件。注冊(cè)后溶诞,就能運(yùn)行包含 Tab 的應(yīng)用或單個(gè) screen 應(yīng)用鸯檬,如清單8所示:
import { Navigation } from "react-native-navigation";
import MainScreen from "./src/screens/MainScreen/MainScreen";
:
// register the MainScreen component
Navigation.registerComponent(
'MainScreen',
() => 'MainScreen'
);
:
:
// Start the (single screen)App
export default () => Navigation.startSingleScreenApp({
screen: {
screen: "MainScreen",
title: "Main Screen"
}
});
如果是基于 tab 的使用,則需要?jiǎng)?chuàng)建更多的 screen 很澄,因?yàn)楸仨氈该鞑煌?tab 及其關(guān)聯(lián)的 screen 京闰,tab 詳細(xì)信息和樣式颜及,例如:
// Start the (tab-based) App
export default () => Navigation.startTabBasedApp({
tabs: [
{
screen: "screen unique name",
label: "label",
title: "title",
icon: icons[0],
navigatorButtons: {
leftButtons: [
{
icon: icons[2],
title: "title",
id: "unique id"
}
]
}
},
{
screen: "screen unique name",
label: "label",
title: "title",
icon: icons[1],
navigatorButtons: {
leftButtons: [
{
icon: icons[2],
title: "title",
id: "unique id"
}
]
}
}
],
tabsStyle: {
tabBarSelectedButtonColor: "black"
},
drawer: {
left: {
screen: "drawer screen unique name"
}
},
appStyle: {
tabBarSelectedButtonColor: "red"
},
});
可以根據(jù)需要通過調(diào)用相應(yīng)的功能在單個(gè)和基于 tab 的 screen 之間切換甩苛。另外,請(qǐng)注意前一個(gè)示例中抽屜的使用俏站⊙镀眩可以為單個(gè) screen 應(yīng)用和基于 tab 的應(yīng)用定義抽屜側(cè)面菜單。
state 管理
在 React(和 React Native)中肄扎,props 和 state 用于控制組件墨林。 props(properties)是用于在創(chuàng)建組件時(shí)自定義組件的參數(shù)。例如犯祠,Button 組件為許多屬性提供支持;在清單10中旭等,title 和 onPress 是 props。
<Button
onPress={onPressHandler}
title="Learn More"
:
/>
屬性由 React 自身設(shè)置(由父組件設(shè)置)衡载,并在組件的整個(gè)生命周期內(nèi)保持固定搔耕。 State 是應(yīng)用內(nèi)的特殊數(shù)據(jù),可根據(jù)需要進(jìn)行更改以驅(qū)動(dòng)組件行為痰娱,比如刷新數(shù)據(jù)弃榨。state 應(yīng)該在構(gòu)造函數(shù)中初始化菩收,并且只能通過調(diào)用 setState 來更改。清單11顯示了 state 的用法:
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {isActive: true};
}
toggleActiveState() {
this.setState(previousState => {
return { isActive: !previousState.isActive };
});
}
render() {
:
}
}
清單11是一個(gè)簡(jiǎn)單 state 管理的示例鲸睛,但如果應(yīng)用對(duì)于許多 screen 組件和組件間狀態(tài)管理更復(fù)雜娜饵,則應(yīng)該利用 Redux。 Redux 是一種更先進(jìn)的 state 管理方法官辈,它提供了一個(gè)實(shí)現(xiàn) state 管理及相關(guān)操作和處理程序的框架箱舞。但是使用 Redux 會(huì)增加應(yīng)用的復(fù)雜性,因此應(yīng)該考慮僅在真正需要它時(shí)使用它(即拳亿,對(duì)于較大的復(fù)雜應(yīng)用)褐缠。
持久化存儲(chǔ)
React Native 使用 AsyncStorage 為持久化存儲(chǔ)提供支持,AsyncStorage 是一個(gè)易于使用的基于鍵值的異步(持久)存儲(chǔ)系統(tǒng)风瘦,對(duì)整個(gè)應(yīng)用而言是全局的队魏。它很簡(jiǎn)單,因?yàn)樗恍枰^多的設(shè)置万搔。在 iOS 上胡桨,它表現(xiàn)為一系列字典或者是文件。在Android 上瞬雹,它基于 SQLite 或 RocksDB:
import {AsyncStorage} from 'react-native'
:
const USERNAMES_KEY = 'Usernames'
const user = {
name: 'John',
last: 'Smith',
username: 'jsmith'
}
// Storing the item
AsyncStorage.setItem(USERNAMES_KEY, JSON.stringify(user))
:
// Get item promise to retrieve the item
AsyncStorage.getItem(USERNAMES_KEY).then((item) => {
const userItem = JSON.parse(item)
})
:
但是 AsyncStorage 有許多限制昧谊,例如性能低下,沒有索引酗捌,也沒有加密呢诬。讓我再說一遍:它沒有加密。如果要存儲(chǔ)大量數(shù)據(jù)胖缤,性能和加密是應(yīng)用的重要因素尚镰,則應(yīng)考慮使用 Realm React Native 等替代方案。 Realm React Native 是跨平臺(tái)的哪廓,性能更好狗唉,支持加密,甚至還帶有版本的 ListView(具有與 React Native ListView 相同的 API 簽名)涡真,它在 Realm 之上進(jìn)行了優(yōu)化分俯,大大改善了對(duì)本地存儲(chǔ)的訪問。 Realm 使用 static schema 的途徑來提高性能哆料。(可以看一下筆者的這篇文章來學(xué)習(xí) Realm 的使用缸剪,傳送門->移動(dòng)數(shù)據(jù)庫 Realm 在 React-Native 的使用詳解
):
class Usernames {
static schema = {
name: 'User',
properties: {
name: 'string',
last: 'string',
username: 'string',
}
}
}
let realm = new Realm({schema: [Usernames]});
realm.write(() => {
realm.create('Usernames', { name: 'John', last: "Smit", username : "jsmith" });
});
網(wǎng)絡(luò)
移動(dòng)應(yīng)用通常是需要網(wǎng)絡(luò)連接的應(yīng)用。移動(dòng)應(yīng)用連接到網(wǎng)絡(luò)以進(jìn)行身份??驗(yàn)證东亦。 React Native 提供不同的網(wǎng)絡(luò) API:
- 最初的 Ajax(異步JavaScript + XML)XMLHttpRequest API
- WebSockets杏节,通過TCP 連接提供全雙工通信通道,也叫做雙向平等對(duì)話
- Fetch API,該系列的最新成員,類似于 XMLHttpRequest拢锹,但具有其他功能谣妻。
清單14使用 fetch API 從服務(wù)器獲取用戶數(shù)據(jù)的 json 文件:
{
"users": [
{ "name": "John Smith", "username": "jsmith"},
{ "name": "Matt People", "username": "mpeople"},
{ "name": "Graciela Lopez", "username": "glopez"},
{ "name": "Jeff Bezos", "username": "jbezos"},
]
}
--
import React from 'react';
import { View, Text, FlatList, ActivityIndicator} from 'react-native';
export default class FetchUsernames extends React.Component {
constructor(props){
super(props);
}
// dispatch the fetch once the component mounts
componentDidMount(){
return fetch('https://...')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.users,
}, function(){
});
})
.catch((error) => {
console.error(error);
});
}
// render the component, populating the FlatList from the
// state.dataSource that was in turn populated from the JSON
render(){
return(
<View>
<FlatList
data={this.state.dataSource}
renderItem={({item}) =>
<Text>{item.name}, {item.username}</Text>}
keyExtractor={(item, index) => index}
/>
</View>
);
}
}
關(guān)于 fetch API 和網(wǎng)絡(luò)的一些注意事項(xiàng):
- 請(qǐng)注意清單14中 Promise 的使用。即使響應(yīng)是 HTTP 404 或 500卒稳,fetch 也不會(huì)失斕0搿(拒絕)。換句話說充坑,它只會(huì)拒絕網(wǎng)絡(luò)故障减江。檢測(cè)非網(wǎng)絡(luò)故障的方法是檢查 status 是否正常返回。
- 默認(rèn)情況下捻爷,iOS 會(huì)阻止未使用 SSL 加密的請(qǐng)求辈灼。解決此問題的唯一方法是添加 App Transport Security。
- 可以使用 NetInfo 來檢測(cè)或檢索網(wǎng)絡(luò)信息也榄。它可以檢測(cè)有網(wǎng)或無網(wǎng)絡(luò)狀態(tài)巡莹,連接類型(Wi-Fi,蜂窩)和有效連接類型(2G甜紫,3G和4G)降宅,不過對(duì)于兩個(gè)端來說這個(gè)還有一些區(qū)別。
結(jié)論
本文僅是對(duì) React Native 提供了一個(gè)高層次的觀點(diǎn)看法囚霸。 React Native 是一個(gè)很復(fù)雜的話題腰根。如果要深究,則需要更詳細(xì)地研究本文所涵蓋的每個(gè)領(lǐng)域拓型。
React Native 是一個(gè)充滿活力且不斷發(fā)展的框架和社區(qū)额嘿。但 React Native 并不像原生應(yīng)用開發(fā)那樣成熟。所以必須為Android劣挫,iOS 和 React Native 的開發(fā)保持穩(wěn)定的環(huán)境册养,包括所有相關(guān)的開發(fā)工具。對(duì) 于React Native 中不存在的組件揣云,可以 Google 搜索捕儒,就可以找到所需內(nèi)容冰啃,請(qǐng)記住所選的第三方庫可能會(huì)更改或維護(hù)可能會(huì)停止或被放棄邓夕,這是一個(gè)要考慮的主要風(fēng)險(xiǎn)。
React Native 并不適合所有人或每個(gè)項(xiàng)目阎毅。這需要考慮創(chuàng)建和維護(hù) React Native 代碼焚刚,工具,開發(fā)環(huán)境和技能集的時(shí)間扇调,精力和成本矿咕,而不是僅僅關(guān)注原生代碼。去年也有大型開發(fā)組織的例子,例如 Airbnb碳柱,它們?cè)?React Native 上投入了大量的精力和投入捡絮,但最終決定回歸純粹的原生開發(fā)。