蘇家嘯,武永成
(荊楚理工學(xué)院 計算機工程學(xué)院,湖北 荊門 448000)
目前移動端使用最廣泛的操作系統(tǒng)主要分成兩派,iOS 和Android。程序員在開發(fā)移動端的某個應(yīng)用時,往往要在這兩個操作系統(tǒng)上分別開發(fā)一個應(yīng)用程序,且大多時候需要兩組從事開發(fā)的技術(shù)人員維護這兩個完全不同的代碼。使用HTML 5 等Web 技術(shù)來實現(xiàn)“一套代碼,多處運行”是比較大眾的解決辦法。但是因操作系統(tǒng)和移動端設(shè)備各式各樣,千差萬別,這些Web 技術(shù)只能解決一些表面問題,如開發(fā)成本等。因為基于Web 的界面與交互在兩個平臺上的體驗并不一致甚至相差甚遠,所以這些技術(shù)并不能解決一些重要的問題,保證應(yīng)用體驗。ReactNative 這個技術(shù)則能很完美地在同一時間解決這些問題,并且能在iOS 與Android 兩個平臺完成代碼的動態(tài)加載。React Native 技術(shù)同JS 被開發(fā)人員作為開發(fā)語言一起使用,它能夠很方便地支持動態(tài)加載機制。
2015 年4 月,美國IT 巨頭Facebook 公司發(fā)布了跨平臺開發(fā)框架,主要應(yīng)用于移動互聯(lián)網(wǎng)。該平臺是在Facebook 過去幾年開源發(fā)布的React 框架的基礎(chǔ)上升級的,采用了一種用于解析和呈現(xiàn)移動設(shè)備上網(wǎng)頁的新方式,ReactNative 允許移動設(shè)備動態(tài)接收和處理來自用戶的輸入,因此前端的軟件設(shè)計師可以在花費較低的學(xué)習(xí)成本的情況下從事移動設(shè)備的應(yīng)用開發(fā)。自下而上的應(yīng)用有以下幾種。
(1)React:基于不同平臺上的React 編寫代碼,“一次學(xué)習(xí),隨處編寫”。React 是用JavaScript 和JSX 語法編寫的,其中JavaScript 的擴展可被看作JSX。通過React,可以在JavaScript和JSX 之間切換。定義HTML 這樣的樹結(jié)構(gòu),JSX 非常簡單明了,這更有利于開發(fā)和維護。
(2)Virtual DOM:Virtual DOM 是一種基于內(nèi)存的輕量級表示方法,UI、JavaScript 和Native 由Bridge 通信通過不一樣的渲染引擎來生成,Native、JavaScript 和UI、React Native 的設(shè)計 核心是所有組件VirtualDom 都存在于內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),只有插入文檔才能成為真正的Dom。而所有Dom 的變動一開始都在虛擬的Dom 中。有一個名為Dom Diff 的算法,它可以對真實的Dom 做出反應(yīng),這種算法能夠明顯改善網(wǎng)頁的功能體現(xiàn),上述發(fā)生和再次實際發(fā)生的波動部分也會對真實的Dom 做出反應(yīng)。
(3)Web/iOS/Android:現(xiàn)在支持主流客戶端Web、iOS 和Android。整個React 的核心思想是打包的程序集,每個程序集保持自己的狀態(tài)和Ul,當(dāng)狀態(tài)改變時自動渲染整個程序集。該組件被視為狀態(tài)機,從初始狀態(tài)開始,而后因為用戶交互而發(fā)生狀態(tài)更改,觸發(fā)UL 重新渲染。ReactionNative 原則上是繼承React.js 的虛擬DOM 思想,通過虛擬視圖實現(xiàn)的。一組由native 完成的視圖(在iOS 平臺上以RCT 開始的一連串的類)被該框架提供。在編寫JavaScript 時(或許更準(zhǔn)確地說,JavaScript 由ReactNative 中的XML 來編寫),由添加虛擬視圖并將其綁定到已注冊的模塊,JavaScript 運行時環(huán)境(即:Use JavaScriptCore for iOS——iOS 版JavaScriptCore),由JavaScript代碼(在本機端執(zhí)行注釋以及編譯)得到對UI 的調(diào)用并阻止它,并將其橋接成用于呈現(xiàn)該構(gòu)件的本機代碼。在布局上也是由CSS 完成的。正因為這樣,React 有兩個和其他框架不一樣的特性:①可以使用JavaScript 編寫基于ReactionNative 的應(yīng)用程序邏輯,所有的原生UI 可以被UI 來保留,HTML 5 的UI 不需要妥協(xié);②用戶界面被React 通過引入一些激進但擁有高度可用性的其他解決方案來構(gòu)建,所以應(yīng)用程序的UI 可以簡略地通過基于應(yīng)用程序如今狀態(tài)的函數(shù)來表明。正是這種基于組件的思維和設(shè)計可以幫助開發(fā)人員封裝自己的代碼,從而提高了開發(fā)效率。
使用ReactNative 技術(shù),開發(fā)人員僅僅只要編寫一次代碼,就可以分別部署在Android 和iOS 操作系統(tǒng)上。對于創(chuàng)業(yè)公司來說,這樣能夠節(jié)省大量編程成本,同時還能騰出功夫讓技術(shù)人員完成其他重要工作。
ReactNative 不是“Web 應(yīng)用程序”,最后一個產(chǎn)品是真正的移動應(yīng)用程序,與用Java 或Objective-C 兩種編程語言編寫的應(yīng)用程序比較,簡直難以分辨。ReactNative 使用的默認(rèn)UI 組件和默認(rèn)應(yīng)用的UI 組件是完全相同的。技術(shù)人員需要做的只是將這些基本組件與Reactor 和JavaScript 的使用方法組合在一起。
ReactNative 擁有Facebook 公司的支持,相信該技術(shù)會發(fā)展良好。一是跨平臺移動框架的發(fā)展,二是開源社區(qū)的能力逐漸壯大,更多的企業(yè)開始進行移動混合開發(fā)設(shè)計。隨著公司版本的不斷更新優(yōu)化,國外用戶規(guī)模逐漸增加,到2020 年6 月,ReactNative 在Github 已經(jīng)擁有11 萬多個star,開源的組件和框架也可以大量使用?;谶@項技術(shù)的應(yīng)用逐漸被美國科技企業(yè)使用。國內(nèi)有越來越多的團隊使用ReactNative 技術(shù),包括知道、cnblogs 和豆瓣。如今,ReactNative 已成為最優(yōu)秀的跨平臺開發(fā)框架之一,因為大量開發(fā)人員和社區(qū)的應(yīng)用而一直在改善,隨著ReactNative 這一移動框架的逐步完善,其在性能和安全性方面越來越成熟,未來國內(nèi)外將有越來越多的企業(yè)將其開發(fā)為主動框架。
React 的框架和CSS 的布局被ReactNative 所使用,因此有前端開發(fā)經(jīng)驗的技術(shù)人員可以減少不少學(xué)習(xí)成本,大大減少代碼量。然而,對于Android 或iOS 開發(fā)者來說,剛接觸的時候需要轉(zhuǎn)換思維方式。
使用ReactNative 開發(fā)APP 的環(huán)境配置比本機開發(fā)簡單,只需轉(zhuǎn)動npm,RN-cli 就可以啟動初始化工程。當(dāng)然,假定是進行iOS 項目,必須安裝XCode,而Android 項目需要單獨配置SDK。
原生應(yīng)用開發(fā)可以基于安卓、iOS、Windows 手機等智能手機底層操作系統(tǒng),原生程序由正在運行的第三方移動應(yīng)用編寫而成,實現(xiàn)特定智能操作風(fēng)格的最大化。但是,這種開發(fā)方式只能針對某些操作系統(tǒng),而不能“跨平臺”。一位開發(fā)人員只能在一個平臺開發(fā),不能一次并行開發(fā)。這樣,當(dāng)客戶要求產(chǎn)品應(yīng)用于多個平臺時,需要多名程序員負(fù)責(zé)各自的部分,這樣將消耗很多的物力和人力。而JavaScript 腳本可以被ReactNative 用來寫入原生程序,大幅度減少了開發(fā)成本。
用戶可能會因為APP 的頻繁升級而感到很煩,畢竟每次更新都必須經(jīng)過APP 的審核,并且蘋果公司的審核也特別麻煩?,F(xiàn)在很多大型的APP 都使用了ReactNative 來進行熱更新,提高更新的效率。
在現(xiàn)在的移動應(yīng)用開發(fā)環(huán)境中,是否有熱更新功能是該應(yīng)用的重要評估標(biāo)準(zhǔn)。如果熱更新功能在該應(yīng)用程序中未被使用,用戶將無法及時查看所需內(nèi)容。對于經(jīng)常更新的移動應(yīng)用程序(如社交或購物),用戶可能無法最新更新。兩周以上的審核周期對一名iOS 開發(fā)者來說更討厭,因為每次開發(fā)人員開發(fā)并迭代新版本時,其更新的內(nèi)容一定要由iOS 的審核機制審核。開發(fā)人員可以通過采用熱更新方式跳過這個令人討厭的審核機制。因此,對于開發(fā)人員來說,特別需要ReactNative 所具有的這種熱更新能力。開發(fā)人員大多通過更新Bundle 文件來使用ReactNative 的熱更新功能。對于ReactNative 應(yīng)用程序,Bundle 的文件實際上就是加載的前端內(nèi)容。Bundle 文件被更新了,就相當(dāng)于整個APP 都更新了,所以只需要具備上傳Bundle 文件下載能力的后臺服務(wù)。然后,每次打開客戶端時,服務(wù)端都將接收到請求,確保最新的Bundle 包文件被包含在內(nèi),然后下載更換即可完成熱更新操作,也可以利用Microsoft公司提出的CodePush 技術(shù),非常方便地實現(xiàn)熱更新。
目前,由于引入“碼農(nóng)”的成本越來越高,代碼的可重用性非常重要,代碼平臺的獨立性也是每個技術(shù)人員的首選。可以共享超過80%的Android 版本和iOS 版本的ReactNative 代碼,在目前主流的原生開發(fā)中是不可思議的。另一方面,由于ReactNative 技術(shù)是在計算機端的React 技術(shù)上發(fā)展起來的,所以將大部分ReactNative 代碼轉(zhuǎn)換成React,也可以用于計算機端的前端開發(fā)。因此,一個開發(fā)可以使用三次,大大減少了人力成本和時間成本,這對于企業(yè)來說是非??上驳?。由于高代碼復(fù)用性和熱更新的優(yōu)勢,其又有高開發(fā)效率,由于采用不同的開發(fā)方法,不需要每次都通過編譯和安裝來見效,模塊化開發(fā)能夠大大提高開發(fā)效率。此外,捆綁文件可以實時更新,因此每次啟動應(yīng)用程序時都可以使用最新的文件,用于快速修復(fù)漏洞。
無論是iOS 還是Android,JavaScript 都可以通過原生代碼接收到消息傳遞,對于它的返回值也可以獲得。換句話說,消息也可以被JavaScript 向默認(rèn)代碼傳遞。正是這種機制,如果結(jié)合使用模塊配置表等方法,本機代碼和JavaScript 代碼就可以達到無縫調(diào)用。
為了使可調(diào)用的原生模塊Module 的名字以及方法被JavaScript 所知道,在ReactNative 初始化的時候,JavaScript 需要接收到一份Module 的配置表。在ReactNative 的框架中提供了一個叫做RCTBridgeModule 的接口。在ReactNative 初始化的時候,經(jīng)過使用objc_getClassList 這個方法能夠使任何類被獲取,而后逐一判別RCTBridgeModule 接口是否被完成了,這樣所有的類模塊就可以被找到了。一個模塊包含很多的方法,其中的一些方法可以被JavaScript 調(diào)用,可以使用RCT EXPORT_METHOD 宏定義將需要顯示的方法包裹。用固定前綴的方法把方法的名字在編譯的時候重新定義一次,這樣就可以方便地查詢以及記錄。所以只要接口與函數(shù)在原生的代碼中被定義了,ReactNative 就會根據(jù)運行時環(huán)境獲取所有的模塊及其方法生成一個利于JavaScript 代碼和原生代碼相互調(diào)用的模塊配置表。
原生代碼集和JavaScript 相互調(diào)用機制的自我實現(xiàn)是ReactNative 的核心,這也是它同其他基于Web 的跨平臺方案的有差異的地方。業(yè)務(wù)代碼使用JavaScript 編寫后,全部在基本階段被解釋為ReactNative,通過UI 呈現(xiàn)和高效邏輯執(zhí)行,其他跨平臺場景的執(zhí)行效率要比ReactNative 的低很多。
原生代碼以及JavaScript 的調(diào)用過程非常復(fù)雜,如圖1 所示。
圖1 Native 與JavaScript 的調(diào)用流程
(1)默認(rèn)模塊的方法被JavaScript 端調(diào)用。
(2)調(diào)用被解析成參數(shù)、方法名和模塊名稱,并傳遞給MessageQueue 對其處理進而被callbackId 生成出來。
(3)參數(shù)ID、模塊ID 以及方法ID 被相應(yīng)的模塊配置表轉(zhuǎn)換為參數(shù)、方法名和模塊名稱。
(4)調(diào)用的參數(shù)和方法被默認(rèn)模塊根據(jù)每個ID 來確定。
(5)先實施底層的代碼邏輯,然后回調(diào)執(zhí)行結(jié)果。
(6)JavaScript 端根據(jù)callbackId 接收執(zhí)行結(jié)果。
這里需要注意的一點是,數(shù)據(jù)不會主動地傳遞給JavaScript 端。調(diào)用OC 方法時,將方法ID、模塊ID 入隊。當(dāng)原生代碼到來并且JavaScript 中的不管哪一個方法被到來的原生代碼所調(diào)用的時候,默認(rèn)代碼都會返回一個隊列,重新運行需要在此隊列中執(zhí)行的方法。因此,ReactNative 是一個基于事件響應(yīng)機制的框架,在沒有操作的情況下不會執(zhí)行錯誤的循環(huán)。
對底層Android 和iOS 系統(tǒng)的應(yīng)用程序使用ReactNative技術(shù),會使整個代碼庫更加復(fù)雜,在深入到對底層基本代碼的debug 時,會比較麻煩,也就是說,維護和開發(fā)的成本會增加不少。
在如今的ReactNative 官方文檔中,可以發(fā)現(xiàn)有些區(qū)分iOS和Android 版本的組件和API。換句話說,嚴(yán)格意義上的“一套代碼、多平臺應(yīng)用”依舊不能真正實現(xiàn)。
ReactNative 是當(dāng)前移動互聯(lián)網(wǎng)設(shè)計開發(fā)最先進的技術(shù)之一,它被用于開發(fā)世界領(lǐng)先的原生應(yīng)用,為不同的移動操作系統(tǒng)平臺提供統(tǒng)一的操作體驗。本文對該技術(shù)產(chǎn)生的背景進行分析,對其底層原理、技術(shù)優(yōu)勢和不足進行了論述。