我們想為用戶設計一款移動端的應用,卻不知從何下手,我們只知道每一個人都希望做一款又酷又好玩兒體驗又十分順滑的應用,然而團隊里沒人有移動端的經驗。
于是,我們最終只好選擇React Native作為我們的開發工具。結果證明,這是一個非常明智的選擇,我們從開始到現在的所思所感,全都總結如下:
為什么要用React Native
我們是一群Web開發者,而不是iOS開發者。我曾參加過幾個在紐約舉辦的有關Swift和Objective-C的線下聚會,但最后我依然認為編寫Ruby和JavaScript代碼最令我愉悅。我們團隊在2015年初開始使用Facebook的React框架并取得了初步成效,React Native面世后,我們一度懷疑像這樣的交叉設備平臺會有很多潛在的問題。但是隨著我們的研究深入,我們越發喜歡它了:
一次學習,隨處可用 交叉設備平臺通常品相不佳,而且只支持不同設備間相同的功能。而React Native雖然基于React.js框架,但為Android和iOS兩個平臺編寫的項目代碼卻不盡相同,它們之間只共享一部分代碼。因此這些代碼在每個平臺上都能調用所有原生組件,發揮其最大的效用。
聲明式的視圖 當初我們在Web平臺用React編寫代碼的時候就已經愛上了這種聲明式的視圖,用React Native在iOS平臺開發延續了這一傳統,如此一來,我們的代碼就變得可預測且bug更少。
請閱讀:響應式編程
為移動平臺設計的Flexbox(彈性盒模型) 我們不了解iOS布局約束求解器的工作原理,但幸運的是,React Native引入了大部分瀏覽器都支持的Flexbox以使布局的過程變得更直觀。
請閱讀:Flexbox指南
iOS約束器(Constraints)
Flexbox
用JavaScript編寫代碼 構建移動應用完全是我們未知的領域,顯而易見,如果我們用已掌握的語言來編寫代碼會節省非常多的時間。況且,我們曾經癡迷于CoffeeScript優雅的語法,而現在React Native已經默認支持了ES6,這讓我們激動不已,因為我們可以很輕松地過渡到新的語法體系中。
請閱讀:用ES6代替CoffeeScript
不用React Native的幾個保留意見
我們深知節省下來的時間再多也抵不過捉襟見肘的可定制性和有限可用的React Native組件。我們也曾猶豫過是否一定要是用React Native,畢竟以下幾條理由確實值得仔細琢磨:
React Native生態系統的限制性 2015年9月,我們剛開始研究React Native,彼時非常多的iOS原生組件已經被實現出來,而且還有更多的功能正緊鑼密鼓地開發當中。然而,我們還是會擔心React Native最終不支持某些我們非常需要的組件,如此一來我們就只能在React Native橋接器的基礎上構建其它相關的SDK了(例如提供對AWS和Mixpanel的支持)。
太前沿 React Native更新非???,支持老版本的代碼有可能(極少數情況下)在新版本中就被廢除。我們在過往的開發周期中遇到過幾次這類問題,最后我們不得不作出這樣的決定:當且只當亟需某些經過嚴格測試的新特性時才會主動升級。
Google搜索到的資料少之又少 為一個新系統編寫代碼意味著很有可能遇到前人沒經歷過的錯誤,這些無法通過搜索得到解決方案的問題遠比我們編寫Ruby on Rails代碼的時候要多。想要找到這些問題的解決方案需要足夠多的韌勁兒:在文檔中定位問題,在源代碼中挖掘可能的漏洞。不管怎樣,對于React Native團隊和它的生態系統而言,只有更多地解決此類問題,多發布一些常規修訂才能給他們帶來更好的信譽。
React Native的包管理
事實證明,支持React Native的組件簡直多到爆炸。無論是ActivityIndicator(加載中指示器)、Alert(警告框)還是Slide(輪播),這些組件與JavaScript中的同類組件并無二異。我無法用語言描述在不了解Objective C和Swift的前提下開發原生iOS應用有多么省心。此外,npm上每天都會出現許多新的代碼包,以下這些我們都很喜歡(排名不分先后):
react-native-simple-store 我們剛開始用的是AsyncStorage,但卻不得不一遍又一遍地重復構建相同的save和get函數。Simple Store是一個基于AsyncStorage的解決方案,它十分出色,可以分分鐘連接到設備的存儲區。Store.get('user').then((user)=> { // 一些代碼}).catch((error) => { console.warn(error)}).done()react-native-vector-icons 這是我們已知的最好的向量圖標包,我們同時使用FontAwesome和EvilIcons,它們可以完美地結合。MaterialIcons、IonIcons和其它圖標庫均可直接通過這個包獲取到。怪異的地方
作為Web開發人員,我們遇到了一些令人感到十分頭疼的問題:
樣式 在React Native中可以使用樣式表,但只能使用非級聯的行內樣式,用這種方式定義的樣式非常難理解。我們可以通過行內越權的方式定義多級樣式來解決這一問題。Styles.js
module.exports = StyleSheet.create({ title: { fontSize: 23, textAlign: 'center', color: blueText, fontFamily: 'Avenir', fontWeight: '700', }, header: { padding: 20, paddingTop: 30, backgroundColor: '#fff', borderBottomWidth: 1, borderBottomColor: '#ccc', },})Component.js...標準樣式如下所示:
style={Styles.header}自定義行內樣式如下所示:
style={{color: 'white'}}我們將二者進行了整合:
style={[Styles.header, {color: 'white'}]}這種hack的方式讓人很不爽……可能有更好的方法可以解決此類問題,但是當時我們想到這個方案的時候壓根兒不了解。
循環調用/導航器你很可能在使用NavigatorIOS的時候遇到此類問題,這是很糟糕的選擇(除遞歸外的大多數循環都很糟糕)。Web路由是單一過程的,你可以獲取到當前位置及歷史位置的所有信息。而在iOS中,你需要將視圖置入?;驈闹腥〕鱿鄳晥D,如果置入一個已存在于棧中的組件將會觸發錯誤。如果調用組件時將當前組件置入到棧中可能會引發調用循環的問題,從而導致程序中斷執行。react-native-router-flux可以幫我們解決這個問題,它能用一種可伸縮的方式推導出我們使用的歷史路徑。
最后的話
React Native是一個優秀的框架,用它來構建移動應用是非常好的選擇。由于我們不了解Swift和Objective C,很難將純原生與React Native兩種實現進行比較,單就使用體驗而言,它已經可以滿足絕大多數的使用場景。我們樂于見到React Native帶給我們的首個移動應用,它也持續發展力圖變得更加完善。最后我始終認為,對于我們這樣一支敏捷靈活的開發團隊而言,這項技術幫我們快速地從Web環境切換到移動應用開發領域,非常感謝!
在后續的幾篇文章中,我將繼續深入剖析我們解決某些特定問題的思路。
登錄和認證API和回調整合iOS SDKs與React Native橋接器作者簡介
Tom Tang,目前任職于HireArt,負責移動開發業務
查看英文原文:http://code.hireart.com/2016/02/24/react-native-ios-app/