移動開發(fā)的發(fā)展?jié)u漸趨于成熟,開發(fā)者的技能樹分布漸漸完善睛廊。隨著大前端的發(fā)展跨平臺技術也衍生除了相關平臺超全。對于移動開發(fā)者來說光酣,也是面臨著新的機遇與挑戰(zhàn)财异,各個公司也嘗試擁抱新技術呈驶,可以說這也是一個趨勢相關的挑戰(zhàn)。由于公司產(chǎn)品,存在Android,iOS兩組開發(fā)人員羹唠,且業(yè)務邏輯與UI幾無差別。對于成本和效率的考慮團隊開始考慮使用React Native 開發(fā)產(chǎn)品谷浅。
開始前準備
RN的開發(fā)語言基于ES6夺姑,整體框架基于React 實現(xiàn)。所以開發(fā)RN必須掌握 ES6和React,這兩者就不在此文討論范圍了。值得一說的是,之前開發(fā)android 十偶,從17年google把kotlin提升到官方語言之后猛频,就開始使用,其中一些語言與思想跟ES6相似坦敌,所以切換到ES6開發(fā),還是很爽的。并且ES6有很多的語法糖,用起來甚是很6茴扁。跟ES5相比有增加了很多語法铃岔,對于java開發(fā)者來說熟悉很多,準守規(guī)范不至于入坑丹弱。如果使用TypeScript那就更熟悉了德撬。React之前沒有接觸過,但是開發(fā)RN那是必須要熟悉的躲胳◎押椋看了看簡單的使用文檔對于Component,Props,State,JSX都要有基本的熟悉,大概就可以開始使用了坯苹。
快速開始
能跑起一個'Hello World'大概是學習一項新技術開始隆檀。這是對環(huán)境以及相關基本的配置成功的一種標志。怎么開始呢?當然是找到官方文檔,里面有相關介紹恐仑。(多說一句泉坐,如果一項技術沒有完善文檔,真的不值得使用)文檔首選官網(wǎng)裳仆,那里是有最新最詳細的介紹和使用腕让。不過是英文的對于國內(nèi)很多人來說,比如我也是很有障礙的歧斟。所幸有中文文章纯丸,雖然跟官方文檔比起來,比較過時静袖,很多沒有翻譯的到位觉鼻。有些也確實,但對于我們的簡單開始是夠用的了队橙。不得不說React Native中文網(wǎng)坠陈,的對于如何搭建開發(fā)環(huán)境是很詳細的,也考慮到了國內(nèi)由于墻的存在產(chǎn)生的一些問題捐康。照著文檔來仇矾,并且保證自己可翻墻,沒有碰到什么問題吹由。通過 react-native init awesome project 生成第一個項目若未,然后react-native run-android 跑起來朱嘴,成功的一刻當然是很開心的倾鲫。不過還好,因為早早在15年rn剛開始出的時候我就已經(jīng)試過了萍嬉,不過那時候我才剛剛入行android乌昔。技術也不行,并且也沒有覺得RN能怎樣壤追,學習成本對于我來說也高磕道,畢竟android都還沒有整明白。也就沒有繼續(xù)下去行冰,說起來還是自己拖延溺蕉,執(zhí)行力低,并且也沒有明確的規(guī)劃悼做。后面RN也是發(fā)展的越來越成熟疯特,但是國內(nèi)應用的還是很少,到去年國外很多大公司開始宣布棄用React Native,這又是另一個話題了肛走。
React native 的能力
能跑起來'hello world'只是一小步漓雅,接下來還面臨著星辰大海。要想走得更遠我們就要確定RN的極限在哪兒。對于這一點就要弄清楚RN的原理邻吞,這一點對于現(xiàn)在的我來說组题,談這個有點不足夠。通過在Android上執(zhí)行adb shell dumpsys activity top.查看一個簡單頁面的原生堆棧抱冷〈蘖校可以看到RN封裝了各個組件。就拿Image來說旺遮,最后顯示在Android上的是ReactImageView峻呕,又是繼承自DraweeView。所以傳遞給Image的屬性最終傳遞給了DraweeView了趣效。這也就是React Native兩個單詞的含義了吧瘦癌。
這如何傳遞,以及js跷敬,與native之間的雙向通信暫且不討論讯私。可以看到西傀,通過這種對原生組件的封裝可以說RN能做到幾乎所有原生可以做到的斤寇。這里可能會問,原生自定義View呢拥褂?這就是RN厲害的一點了娘锁,我們可以重用已經(jīng)有的自定義View。通過RN的預留接口饺鹃,只需要先定義好需要暴露的屬性莫秆,然后通過幾個步驟就可以實現(xiàn)在RN中調(diào)用自定義View了。這個能力真的是強悔详。也許還會問镊屎,怎么實現(xiàn)高性能代碼呢,比如多線程茄螃?眾所周知缝驳,js是單線程模型,雖然ES6實現(xiàn)異步也有好幾種方式归苍,但是跟原生比相比還是差的用狱。這之間的差距就涉及到我知識的盲區(qū)了。同樣的RN也提供了給我們接口實現(xiàn)拼弃,我們可以編寫原生代碼夏伊,然后定義好接口,通過RN提供的接口暴露出去肴敛。就可以在RN中調(diào)用原生模塊代碼署海,同時由于通信是雙向的吗购,所以原生也可傳遞給RN。也就是幾乎不存在實現(xiàn)不了的情況砸狞。作為例子可以編寫一個Toast模塊通過實現(xiàn)RN提供的接口封裝Toast捻勉,實現(xiàn)RN中調(diào)用我們自己實現(xiàn)的Toast組件,這個在官方文檔上有完整demo存在刀森。
但這個過程還是很繁瑣的踱启,如果模塊很復雜就要考慮到很多架構上的實現(xiàn)。這樣就對原生開發(fā)能力有一定要求研底,但這種需求畢竟是少數(shù)埠偿,并且到如今生態(tài)已經(jīng)很完整,很多第三方庫榜晦,sdk等都推出了RN版本冠蒋,已經(jīng)定義好了接口給RN調(diào)用。以上確定了RN與原生之間的交互補助了RN的短板乾胶。那么RN本身可以在不依賴于原生的極限能力又有那些呢抖剿?前文提到,RN最后提供的都是原生組件识窿。那么RN能多大程度上不依賴于原生斩郎,僅僅通過自身實現(xiàn)各種交互效果呢,還有性能怎樣呢喻频?九宮格顯示圖片缩宜,是非常常用的一個控件。通過對不同數(shù)量的圖片甥温,在限制的區(qū)域內(nèi)锻煌,布局并動態(tài)的調(diào)整大小。在Android開發(fā)中窿侈,一般來說通過自定義ViewGroup炼幔,在onMeasure中實現(xiàn)調(diào)整算法,并對每個子view進行測量史简。再在onLayout 在確定算法,并且layout每一個子View到指定位置即可實現(xiàn)肛著。當然最后還要考慮到加載圖片圆兵,以及定義屬性等問題。在RN中整體的思路是一致的只是很多步驟不再需要了枢贿。首先計算如何根據(jù)圖片數(shù)量調(diào)整布局位置和每個Image的大小殉农。拿到大小,Android中是把大小傳遞給ImageView#onMeasure局荚,在RN中則指定style中的width,height.剩下的就是layout了超凳。這一點有所不同愈污,RN采用css標準布局方式,支持flex布局轮傍。所以我們是按照RN中定義的布局方式布局暂雹,這樣就可以了。剩下的圖片加載创夜,則直接定義Image加載圖片的屬性就可以了杭跪。整個過程效率是很高的,并且是邏輯清晰的驰吓,最后執(zhí)行的效果也不錯涧尿。通過這個例子可以知道RN實現(xiàn)普通的或者一些復雜的效果是完全可以的,性能上也能夠得到很好的解決檬贰。也許會說手勢姑廉,動畫對于RN來說怎么樣,動畫對RN來說一直都是個影響性能很關鍵的一點翁涤,特別是在Android中庄蹋。RN提供了相關的api來實現(xiàn),因為我也沒有很深入的去測量具體性能怎樣迷雪,所以無法給出性能相關的結論限书。不過這些api常用功能還是實現(xiàn)的沒問題的,畢竟是對于原生功能的封裝章咧。我想倦西,通過以上的描述可以對RN做一個總結,對于普通業(yè)務場景中的開發(fā)RN是完全HOLD住的赁严,對于需要高性能Native編程扰柠,Native也完全支持,對于Native已有組件RN也還是沒問題疼约。所以RN能辦得到比我們想像得更多的事兒卤档。
生態(tài)與框架
從2015年RN開源到如今,已經(jīng)走過了四個年頭程剥。隨著社區(qū)中開發(fā)者不斷的努力劝枣,現(xiàn)在的RN早已不是當初一堆坑的RN了。在我面前的是成熟织鲸,煥發(fā)著無限能力的RN舔腾。這一切都離不開RN的整個生態(tài)和第三庫。打開github的 awesome-react-native搂擦,可以看到翻不到底的項目稳诚。這些項目都是開發(fā)者的努力,也是我們可以使用并借鑒的瀑踢。正是由于這些項目扳还,RN才可以達到現(xiàn)有的成熟和效率才避。對于一個應用來說,路由始終是一個繞不過去的關鍵問題氨距。在web中桑逝,很簡單,僅僅通過<a/>
標簽的href屬性就可以實現(xiàn)跳轉衔蹲。Android中通過Intent也很簡單肢娘。但是在RN中情況就復雜很多了,早期并沒有很好的解決方案舆驶,通過社區(qū)的努力 React-Navigation誕生了〕鹘。現(xiàn)在已經(jīng)到3.x版本∩沉可以很方便的實現(xiàn)頁面之間的路由拘荡。像這樣幫助開發(fā)的開源項目還有很多例如Redux等。共同支撐起來RN的生態(tài)撬陵。
項目實戰(zhàn)
在實踐中學習珊皿,我一直認為是掌握一門技術的最好方式。在學習中我也實現(xiàn)了一個gank.io的RN版本巨税◇ǎ總得來說在這個過程中把各個RN中的知識點都過了一遍,也形成了一套開發(fā)套路草添,也對RN項目的理解更深了驶兜。RN基于狀態(tài)管理,這一點對于開發(fā)業(yè)務來說還是很方便的远寸。規(guī)劃好了狀態(tài)抄淑,業(yè)務邏輯清晰基本的實現(xiàn)基本沒有問題。如果項目大起來驰后,狀態(tài)的管理會導致效率的降低肆资,這時候通過Redux是很必要的。對于組件的狀態(tài)封裝一個下拉刷新上拉加載的組件灶芝,是一個很好的例子郑原。這個組件需要有 正在刷新,可以加載监署,錯誤颤专,加載完成等狀態(tài),實現(xiàn)的細節(jié)不多描述钠乏。不同的狀態(tài)展示不同的UI真的是很容易。react-navigation 雖然功能強大春塌,但我用著還是不爽晓避,可能是還沒有用熟悉吧簇捍。項目的架構,參考了github上成熟的開源項目俏拱,這一點跟android項目其實沒差暑塑,大概可以按照相同的方式組織代碼。不過原則還是要與一個統(tǒng)一的規(guī)范锅必。剩下的就是業(yè)務邏輯了事格,這也是一個程序的內(nèi)容和功能所在。業(yè)務邏輯其實是沒多大差別搞隐,只要想好了實現(xiàn)步驟驹愚。不過具體的實現(xiàn)肯定是有差的。在RN中劣纲,就很爽fetch函數(shù)返回的Promise對象那可是方便逢捺。而且通過State狀態(tài)管理,很方便的切換各個狀態(tài)癞季,再借助生態(tài)中提供的一些庫劫瞳,可以說只要不是太復雜的業(yè)務。實現(xiàn)起來難度并不高绷柒≈居冢總體而言實現(xiàn)一個展示類的App用RN真的爽。如果細節(jié)一些我想需要考慮的問題還會比較多废睦,比如對Android中機型的適配,如何編寫高性能的代碼伺绽,性能管理等。