原文鏈接:http://blog.zhaiyifan.cn/2016/08/04/android-new-project-from-0-p10/
本篇來講講 React Native 和 Redux扶认,和其他一上來就啪啪啪丟上來一堆翻譯的東西不同早像,本文會從簡單的例子入手,讓大家能快速地明白 React Native 是什么蚕冬,Redux 和常見的 MVC际插、MVP 等有什么區(qū)別恰力,怎么去組織一個 Redux 架構(gòu)的 React Native 項(xiàng)目捻艳。
為避免大家還沒入門就放棄,預(yù)計(jì)下一篇才會從我們項(xiàng)目中的實(shí)踐出發(fā)舆床,講講更復(fù)雜的應(yīng)用場景。
什么是React Native
React Native 使你能夠基于 JavaScript 和 React 在原生平臺上構(gòu)建應(yīng)用,提倡的是 “l(fā)earn once, write anywhere”挨队,復(fù)用代碼谷暮,提高開發(fā)效率。
項(xiàng)目由 Facebook 開源驅(qū)動盛垦,在過去的近一年中更新很活躍湿弦。文檔建議直接看官網(wǎng)的 React Native,中文站有點(diǎn)坑腾夯。
支持系統(tǒng):Android 4.1 (API 16) 以及 >= iOS 7.0颊埃。
關(guān)于 React,可以參見之前為掘金翻譯計(jì)劃翻譯的 React.js 新手村教程蝶俱,簡單來說 React 將應(yīng)用分為一個個動態(tài)可復(fù)用的組件 —— View的渲染(JSX)班利、數(shù)據(jù)如何綁定到顯示、狀態(tài)的變更(State)榨呆、屬性(Props)都包含在組件內(nèi)部罗标。
整個應(yīng)用由一個個組件搭積木而成(組件式開發(fā)),而每個組件則由狀態(tài)驅(qū)動而變更积蜻。
React Native 正像它的名字闯割,將 React 帶到了原生世界,和 H5 不同的是竿拆,我們不再使用 CSS 和 HTML宙拉,而只有 js 為伴。我們也不再有那些 div
, input
這些標(biāo)簽丙笋,而是由 View
, TextInput
等等取代鼓黔,更符合原生開發(fā)者們的習(xí)慣。布局上不见,幸而有強(qiáng)大的 Flexbox
支持澳化,如果開發(fā)者們之前有使用或者看到過 Google 在 GitHub 發(fā)布的 Android 版 FlexboxLayout
,相信對它會很熟悉稳吮。原生開發(fā)中的頁面棧缎谷,也由 Navigator
進(jìn)行了實(shí)現(xiàn)(在 Android 上還有 BackAndroid
的返回鍵支持)。
與 WebView 不同灶似,React Native 運(yùn)行的界面列林,最終會被解釋映射為原生的 View,可以直接使用布局邊界或者 Hierarchy Viewer 看出層級(js 文件會打包為一個bundle酪惭,位于assets下面希痴,RN引擎會加載并進(jìn)行解釋映射)。
好處
- 體驗(yàn) web 開發(fā)的便捷春感,不再需要編譯砌创,重新加載一下 js 就行了
- 可以直接使用 Chrome 或者 Nuclide 調(diào)試
- Android / iOS 兩端可以共享很大一部分代碼(RN 還在進(jìn)行 Windows, MacOS, Node-webkit 等平臺的支持)
- 熱更新虏缸,JS bundle 下發(fā)一下新的就行了(當(dāng)然也有一定局限性,如果是 hybrid嫩实,則 native 的 RN module 部分不能更新)
壞處
- 前端開發(fā)不會原生做不了 React Native(除非你能真只用自帶的那些東西)刽辙,而且理解那些 RN 提供的組件也會很頭暈(需要同時了解 Android 和 iOS)。
- 原生開發(fā)需要一定成本的學(xué)習(xí)實(shí)踐才能掌握 React Native甲献。畢竟 ES6 不像過去的 JS 那么傻瓜式了宰缤。
- React Native 目前仍然處于快速迭代開發(fā)的階段,你永遠(yuǎn)也不知道下個版本自己升級需要修改多少原來的代碼晃洒。
- React Native 的資料較少慨灭,尤其是國內(nèi)的,更尤其是 hybrid 開發(fā)的(GitHub 上的開源項(xiàng)目大多是純 RN 的)球及。
什么是Redux
Redux 本身和 React 并沒有特別緊密的聯(lián)系氧骤,而是 Facebook 提出的 Flux 架構(gòu)的一種優(yōu)秀實(shí)現(xiàn),可以搭配其他任何框架一起使用桶略。在 React 上使用语淘,需要搭配 react-redux(如此一來 Redux 可以不局限于 React诲宇,而讓社區(qū)發(fā)展出更多的 redux-* 中間件)际歼。
Redux 在 React 的基礎(chǔ)上(state 和 props),增加了 store姑蓝、action鹅心、reducer 的概念,規(guī)范了全局一個 state纺荧,從而只需要根據(jù)這個 state 就能回朔出整個應(yīng)用的狀態(tài)旭愧。組件通過 dispatch 將 action 傳到 store,reducer 根據(jù)原來的 state 以及 action宙暇,返回新的 state输枯,組件根據(jù)新的 state 渲染界面。
Redux 是一個可預(yù)測的狀態(tài)容器占贫,即只需要有狀態(tài)樹桃熄,就能還原出“事發(fā)現(xiàn)場”。
從例子看項(xiàng)目
為了避免說一大堆概念型奥,大家一頭霧水瞳收,似懂非懂,這里拿一個例子來講講 React Native 和 Redux 結(jié)合后的效果厢汹,盡量避免代碼的出現(xiàn)螟深,而以圖和文字代替。
Counter烫葬!沒錯界弧,就是 Counter凡蜻,不是 TODO,TODO已經(jīng)被黑的不成樣了夹纫。
項(xiàng)目源碼位于:example-react-native-redux咽瓷。包含了 Counter
和 Counters
兩個子項(xiàng)目。前者是單個的計(jì)數(shù)器舰讹,后者則在前者的基礎(chǔ)上增加了可以加減計(jì)數(shù)器個數(shù)的功能茅姜,相對更復(fù)雜一些,不過引入了一些不錯的實(shí)踐可以參考月匣。
運(yùn)行效果
先看看最后的效果钻洒,方便對應(yīng)后面的解說。
第一個 Counter 項(xiàng)目很簡單锄开,就是一個文本框加上兩個按鈕素标,一個加1,一個減1萍悴。
第二個 Counters 項(xiàng)目在前者的基礎(chǔ)上(使用了 Counter 組件)头遭,可以增加任意個計(jì)數(shù)器,還添加了帶延遲的加1功能癣诱,來模擬耗時操作计维。
Counter
先看看Counter,我們從物理架構(gòu)和動作流兩個角度來進(jìn)行觀察撕予。
目錄下鲫惶,有以下文件:
index.android.js 和 index.ios.js 分別是 android 和 iOS 的 rn 入口,通常內(nèi)容是相同的实抡。
android 為 Android 的工程目錄欠母,下面有我們熟悉的 build.gralde。
ios 為 iOS 的工程目錄吆寨,包含了 xcode 的項(xiàng)目赏淌。
app 就是 rn 的目錄,包含了 Android 和 iOS 項(xiàng)目共享的 js 源碼啄清。
node_modules 是 node 通過解析 package.json 下載的依賴六水。
物理結(jié)構(gòu)
CounterApp.js 則是整個應(yīng)用的實(shí)際入口。
動作流
且不談那些具體的 bind 和 createStore 操作盒延,我們來看看當(dāng)發(fā)生交互的時候缩擂,整個動作的分發(fā),拿點(diǎn)擊加號為例:
onPress 事件觸發(fā)了后續(xù)的一系列活動添寺,而 Counter Component 的 action function 則由外部通過 props 傳入(在這里胯盯,是 CounterApp 的 render 函數(shù),如下)计露。
再看看 store 的創(chuàng)建博脑,在 App.js 入口:
而 Component 也不是直接調(diào)用 action 的 function憎乙,而是通過 bindActionCreators 注入到組件props中(這里是通過 react-redux 進(jìn)行的,不是 redux 自身的東西叉趣,可以理解為 react 和 redux 之間的膠水):
通常我們會在智能組件的末尾使用:
export default connect(mapStateToProps, mapDispatchToProps)(CardDetail);
這樣來把 state 以及 action 注入泞边。
Counters
接著我們來看看更為復(fù)雜的 Counters 項(xiàng)目,頂層目錄結(jié)構(gòu)類似疗杉,不再贅述阵谚。
看完上面的 demo 動圖后,相信大家對下面的解說會更容易理解烟具。
物理結(jié)構(gòu)
我們來詳細(xì)講一下 modules 下的 app 目錄中的文件組織梢什。
actions.js 和剛才一樣,定義了一個個的 action朝聋,略有不同的是由于這次有異步的操作嗡午,所以涉及到了 dispatch 函數(shù),關(guān)于 dispatch 可以查看官方文檔冀痕。
constants.js 定義了所有 action 的 type荔睹,以及 App 的名字。
reducers.js 一樣根據(jù) action(payload 和 type)以及原來的 state 返回新的 state言蛇,另外僻他,這里還進(jìn)行了 initial state 即初始狀態(tài)的定義(我們也可以把它放到單獨(dú)的文件中)。
App.js 定義了頁面的布局(渲染和 action)猜极,導(dǎo)出了 connect 生成的 container中姜。我們簡單看一下 render 部分是怎么做的消玄。
怎么樣跟伏,JSX 是不是挺容易理解的?
動作流
Counter 本身的動作流上面我們已經(jīng)舉例過了翩瓜,本工程中增減計(jì)數(shù)類似受扳,唯一的區(qū)別是 action 不只有 type,還帶了 payload(id)來標(biāo)示不同的計(jì)數(shù)器兔跌。
所以這里我們拿增加計(jì)數(shù)器的點(diǎn)擊事件來做例子勘高。
看上去是不是跟上面的差不多?剩下的那個 incrementWithDelay 其實(shí)也差不多坟桅,只不過返回的是一個function华望,在 setTimeOut 回調(diào)中才進(jìn)行 dispatch(thunk middleware 會幫我們進(jìn)行處理)。
總結(jié)
上面我們通過物理結(jié)構(gòu)和活動圖大致了解了 React Native 上的 Redux 架構(gòu) app 是如何工作的仅乓。具體的細(xì)節(jié)赖舟,建議大家還是去查看 GitHub 上的源代碼,通過上面的講解后夸楣,應(yīng)該不難理解宾抓。
技術(shù)棧
我們目前實(shí)踐的React Nataive技術(shù)棧:
- immutable.js
- react
- redux
- react-redux
- redux-thunk
- redux-logger
- redux-mock-store
- react-native-router-flux
- react-native-simple-store
- regenerator
- undefined
- jest
更多閱讀
- JavaScript
- 項(xiàng)目
- 八卦
- 如何看待阿里無線前端發(fā)布的Weex?
- weex&ReactNative對比子漩,大頭鬼對兩者的對比,下面還有阿里P8的評論石洗,評論很精彩幢泼,記得一頁頁看過去哦,哈哈讲衫。