由于業(yè)務(wù)上的需要跃须,我們業(yè)務(wù)線接到需求要將部分頁面進行 RN 的改造,很開心的接到了這個任務(wù)娃兽,一心歡喜的覺得可以學(xué)點新東西菇民,然而所謂的 write once use anywhere 并不是那么簡單。
首先網(wǎng)上關(guān)于 RN 基礎(chǔ)環(huán)境搭建的文章一搜一大堆投储,再加上我司我對于 RN 本身進行了二次開發(fā)和一些優(yōu)化第练,所以部分場景有所不同,防止造成誤導(dǎo)玛荞,這里就不在進行介紹了娇掏。
本文主要涉及從學(xué)習(xí) RN 到我們業(yè)務(wù)線 RN 成熟版本上線過程中遇到的問題。
語言了解
學(xué)習(xí) RN 的第一步還是對于語言的了解勋眯。其實 RN 主要用到語言就是 JavaScrip 婴梧,其實 JS 的學(xué)習(xí)相對比較簡單下梢,因為之前就對前端有一些了解。我當時主要看了 ES6 相關(guān)的所有語法相關(guān)的知識塞蹭。相關(guān)知識
在了解了最新的一些基本語法和特性之后孽江,我們就可初步進行開發(fā)了。
在開發(fā)過程中番电,我們發(fā)現(xiàn)因為 JS 是弱類型語言岗屏,所以我們在一開始寫的時候,就直接將服務(wù)器返回的 json 對象作為對象一直向下的傳遞漱办。但是這個過程體驗極差这刷,因為這里需要考慮如果將來服務(wù)端改字段名,是否需要全局搜索進行更改(在我看來這樣的方式極為低效)娩井,而且涉及到合作的時候暇屋,你傳遞一個 json 對象,讓接收參數(shù)開發(fā) UI 的同學(xué)一臉懵逼,這個 JSON 里的字段都用來做什么洞辣?
對于客戶端開發(fā)的同學(xué)率碾,舉個很簡單的例子解釋這個問題,界面間傳遞參數(shù)或者 service 回調(diào)回來參數(shù)都是 dictionary 那么后續(xù)的開發(fā)和維護成本比起傳遞都是 model 在維護和開發(fā)成本上差距都是巨大的屋彪。
在這個時候所宰,我們向前端的同學(xué)請教了相關(guān)的問題。得到答復(fù)是畜挥,他們一般在開發(fā)的過程中一般的解決方案大概代碼如下
let model = { param1 = serverJson.Param1, param2 = serverJson.Param2, }
然后將轉(zhuǎn)換后的 model 進行傳遞仔粥,這樣的方式解決了服務(wù)端字段發(fā)生改變需要全局搜索進行修改的問題,但是并沒有解決 json 對象傳遞代碼可讀性差和維護成本高的問題
后來蟹但,我在網(wǎng)上找了一些相關(guān)的資料躯泰,同時看了一些 GitHub 優(yōu)秀的開源項目,其實 JS 是可以寫成強類型語言的樣式的华糖。JS 強類型
最后我們同時選擇了 Flow 和比較好的 RN 插件 prop-types
來做輔助麦向。
于是乎我們代碼就成了下邊的樣子
static propTypes = {
param1: PropTypes.number,
param2:PropTypes.number,
data:PropTypes.array,
array:PropTypes.array,
model:PropTypes.objectOf(Model)
}
scrollToIndex(params: {
animated?: ?boolean,
index: number,
viewOffset?: number,
viewPosition?: number,
}) {
}
這樣在可讀性和可維護性方面都得到了極大的提升。我一直認為這樣的調(diào)研極為重要客叉,因為這對于后續(xù)的開發(fā)極效率極為必要K薪摺!兼搏!
基本組件
在開發(fā)的過程中卵慰,需要用到無數(shù)的基礎(chǔ)組件,所以對于 RN 的自然需要有詳細的了解佛呻。
我主要是在 React Native 中文網(wǎng) 上進行學(xué)習(xí)裳朋,其實很多東西,再用到時候直接使用即可吓著。簡單易懂鲤嫡。此外在界面布局上學(xué)習(xí)下 flexbox
相關(guān)的知識和 CSS 相關(guān)的知識即可送挑。(在此不做展開了)
此外需要對于 RN 組件的生命周期有一個很好的了解。這個在開發(fā)過程中十分重要E邸L韪!可以參考 React Native 中組件的生命周期
事件處理
在開發(fā)的過程中罢荡,我們發(fā)現(xiàn)封裝的小的 view 組件事件的向上傳遞問題和客戶端使用 delegate 一直向上傳遞很相似赡突,層層傳遞寫起來不簡潔对扶。感覺做了很多堆砌的工作区赵,因為之前對于 Vue
有一定的了解。第一時間想到了 Redux , 但是組里的同學(xué)對于 Redux 并沒有過了解浪南。擔心 Redux 的學(xué)習(xí)成本,但是我們溝通了這個問題之后笼才,基本使用組里同學(xué)很快就基本掌握。
之后我們的開發(fā)過程中络凿,使用起來感覺很爽骡送。而且學(xué)習(xí)成本也并不是很高。所以在這里極力的推薦 Redux 文檔 絮记,當然也可以看看 Flux摔踱。
在客戶端開發(fā)過程中,我們部分場景也放棄了事件層層回調(diào)的 delegate 或者 block 的方案怨愤。我們使用了蘋果在 UIControl 中更為常見的事件處理模式 Target-Action 派敷。 有興趣的朋友可以嘗試下,希望能理解其中的不同和為什么蘋果會使用 Target-Action 來設(shè)計 UIControl 來設(shè)計事件的傳遞撰洗。
調(diào)用原生
因為 RN 本身提供的能力有限篮愉,比如數(shù)據(jù)的緩存,SDWebImage差导,數(shù)據(jù)庫等都需要原生進行實現(xiàn)试躏。這個時候就需要我們在原生進行實現(xiàn)。相關(guān)的文章很多设褐,這里暫不做擴展颠蕴。但是相關(guān)的知識的學(xué)習(xí)很重要。
性能優(yōu)化
因為我們第一期 RN 化涉及到的頁面不是很多助析,所以相關(guān)的經(jīng)驗并不是很多裁替。下邊只是簡單的介紹,其實 RN 現(xiàn)在依然存在很多的問題貌笨,寫出了原生類似的效果并不意味著真的能替代原生弱判,在 RN 端還是需要很多優(yōu)化。
我們在開發(fā)過程中遇到的問題大致有如下锥惋。
RN 的 scroll 回調(diào)并不是連續(xù)性的昌腰,因此如果根據(jù)試圖滾動的 contentOffSet 來調(diào)整其它試圖的位置开伏。存在嚴重的丟幀現(xiàn)象,具體原因在 RN 的 issue 中查找遭商。對于這個問題固灵,我們當前的解決方案是找 UI 同學(xué)更改了交互效果。其實更好的解決方案是調(diào)用原生方案進行解決劫流,但是我們的基礎(chǔ)組件部門寫的原生方案同樣存在很嚴重的性能問題巫玻,所以暫時也放棄了。因為時間緊迫祠汇,也沒有在做深入研究仍秤。之后會有后續(xù)研究。
RN 原生的 Image 是不存在 placeHold 概念的可很。想寫出 placeHold 的效果诗力,還是需要調(diào)用原聲。
RN 提供的基礎(chǔ)組件無論 FlatList 還是 VirtualizedList 在實際展示數(shù)據(jù)量較大的列表時 Facebook 雖然比起 ListView 做出了一些優(yōu)化但是還是存在問題我抠,我們在 iOS 端查看內(nèi)存加載 160 條左右的數(shù)據(jù)苇本,內(nèi)存可以暴漲到 300 M+,而原生的內(nèi)存增長 3 M 以內(nèi)。這樣的性能差距... 而我們在每次上線之前都有 Monkey 的性能測試菜拓,所以對于內(nèi)存暴漲問題瓣窄,我們在 RN 的 issue 中找到很多對應(yīng)的提問。我最終找到了開源的庫 優(yōu)化的 FlatList. 但是這個開源庫真的簡單到連 demo 都沒有... 而且因為我們的 FlatList 還有上拉刷新下拉加載 loading 等功能纳鼎,所以不能直接使用俺夕。為此專門看了很少的源碼,理解思想后在自己添加到了我們的項目中喷橙。
在上邊的優(yōu)化過程中啥么,了解到一種很重要的優(yōu)化方式,就是善于用 PureCompoment 來優(yōu)化自己的組件贰逾。相關(guān)文章
當然上邊的方法雖然很大程度上解決了內(nèi)存暴漲的問題,但是同時帶來了新的問題悬荣,就是滑動過程中,每個 cell 的圖片是重復(fù)加載的疙剑,這又大大的消耗這用戶的流量氯迂。于是又要封裝原生的 imageView 來替代當前 image 組件。(主要為了 SDWebImage 和 Fresco 的功能)
同時對于 RN 來說做圖片和數(shù)據(jù)的懶加載都比原生相比麻煩一些言缤,但是在開發(fā)過程中懶加載一定是一個要經(jīng)辰朗矗考慮的問題才能更好的優(yōu)化程序的性能。
除此之外還有動畫等等的坑也是一點一點走過,RN 雖然是多端復(fù)用,但是確實存在一些弊病螟左,對于替代原生的想法聘殖,我認為還有很長的路要走。優(yōu)化這里就不說更多了垦写,因為很多問題和場景還是要在實際的開發(fā)中去發(fā)現(xiàn)和解決問題的瞎抛。
其他相關(guān)知識
在網(wǎng)絡(luò)請求部分钓株,對于網(wǎng)絡(luò)請求層還要學(xué)習(xí) Promise 的用法和相關(guān)知識您单。
打包斋荞、拆包、發(fā)布
因為這一塊基礎(chǔ)數(shù)據(jù)平臺已經(jīng)為我們開發(fā)好了虐秦,所以我們每次發(fā)布只是在后臺管理系統(tǒng)上進行簡單的點擊就能完成平酿,這里不做詳細展開,后續(xù)會進行詳細的了解并進行說明悦陋。
我一直認為 CI 是提高程序開發(fā)效率的必備工具蜈彼,所以雖然當前對于此不甚了解,也將此項寫上叨恨,希望大家都可以對于這一部分有足夠的重視柳刮。