嚴(yán)新巧
摘要:由于移動(dòng)互聯(lián)網(wǎng)的熱潮,很多從事傳統(tǒng)行業(yè)的新人涌入移動(dòng)互聯(lián)網(wǎng),這導(dǎo)致移動(dòng)互聯(lián)網(wǎng)移動(dòng)開(kāi)發(fā)者稀缺,開(kāi)發(fā)產(chǎn)品以及創(chuàng)業(yè)的成本大大增加。 由于移動(dòng)平臺(tái)IOS與Android開(kāi)發(fā)的特性,導(dǎo)致開(kāi)發(fā)速度慢,問(wèn)題多。Android的開(kāi)放性導(dǎo)致各平臺(tái)眾多,開(kāi)發(fā)者苦不堪言,而基于Html5的解決方案又有自己的性能問(wèn)題,一直未能解決開(kāi)發(fā)效率。該文通過(guò)分析當(dāng)前移動(dòng)開(kāi)發(fā)遇到的問(wèn)題,對(duì)React Native 進(jìn)行研究,從一個(gè)新的角度去解決這些問(wèn)題。
關(guān)鍵詞:移動(dòng)互聯(lián)網(wǎng);混和開(kāi)發(fā);React Native
中圖分類(lèi)號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2016)32-0076-02
1 研發(fā)開(kāi)發(fā)現(xiàn)狀
隨著移動(dòng)互聯(lián)網(wǎng)的高速發(fā)展,移動(dòng)開(kāi)發(fā)越來(lái)越熱門(mén),目前市場(chǎng)上實(shí)現(xiàn)做一個(gè)移動(dòng)端產(chǎn)品,客戶(hù)端主要考慮兩個(gè)平臺(tái),一個(gè)是Android平臺(tái),一個(gè)IOS平臺(tái),Android平臺(tái)是Google開(kāi)源的系統(tǒng),IOS是蘋(píng)果公司封閉的一套系統(tǒng),由于這兩者的語(yǔ)言以及平臺(tái)的不同,開(kāi)發(fā)一個(gè)應(yīng)用,需要使用不同的語(yǔ)言,由不同的人員共同完成相同功能系統(tǒng),而每個(gè)系統(tǒng)的更新,都很麻煩,都需要開(kāi)發(fā)者重新上傳,然后審核,用戶(hù)才能更新,IOS的審核至少需要一周,所以對(duì)于產(chǎn)品運(yùn)營(yíng),無(wú)疑會(huì)加大時(shí)間投入。這就如以前做桌面程序,開(kāi)發(fā)者每開(kāi)發(fā)一個(gè)應(yīng)用程序都需要將應(yīng)用開(kāi)發(fā)程序上傳到互聯(lián)網(wǎng)上,提供給用戶(hù)一個(gè)下載地址,用戶(hù)需要自己下載安裝,之后的更新需要用戶(hù)自行更新,而不像現(xiàn)在互聯(lián)網(wǎng)上的網(wǎng)站,只需輸入一個(gè)網(wǎng)址就可以實(shí)現(xiàn)遠(yuǎn)程更新。
移動(dòng)開(kāi)發(fā),特別是Android開(kāi)發(fā)至今缺乏最佳實(shí)踐,很多類(lèi)和接口有多種實(shí)現(xiàn)方式,開(kāi)發(fā)者都按自己熟悉或喜歡的模式來(lái)進(jìn)行開(kāi)發(fā),導(dǎo)致想要讀懂他人的代碼很費(fèi)勁,后續(xù)維護(hù)起來(lái)問(wèn)題較大。由于Android的開(kāi)源性,每個(gè)廠商都可以定制自己的Android系統(tǒng),定義不同的分辨率,這對(duì)Android開(kāi)發(fā)人員來(lái)說(shuō),要開(kāi)發(fā)同一個(gè)產(chǎn)品必須要滿(mǎn)足不同的Android版本以及眾多的分辨率,開(kāi)發(fā)效率必然大打折扣。
2 目前解決方案
由于原生開(kāi)發(fā)會(huì)遇到不同的問(wèn)題,所以現(xiàn)在普遍的解決方案是采用Html5方案,即用Html5、Css、Javascript來(lái)實(shí)現(xiàn)客戶(hù)端的展示與后臺(tái)數(shù)據(jù)交互。再通過(guò)WebView控件在每個(gè)平臺(tái)上分別打包,由于各個(gè)資源都是放在云端,所以可以做到一次開(kāi)發(fā),處處使用。這種方案很多,包括比較出名的PhoneGap與APPCAN。這種方式真正做到了開(kāi)發(fā)一次,多次運(yùn)行的目的,其采用了標(biāo)準(zhǔn)的W3C標(biāo)準(zhǔn),能直接讓W(xué)eb APP直接運(yùn)行,而采用的語(yǔ)言也是主流的Html5,Javascript,CSS3,這使得以前做前端的工程師也能開(kāi)發(fā)出Android,IOS的應(yīng)用。
這種方案采用平臺(tái)各自?xún)?nèi)置的WebView組件,具有以下兩個(gè)特點(diǎn):
1)WebView組件實(shí)質(zhì)是移動(dòng)設(shè)備內(nèi)置的瀏覽器,正是由于這中特性,使Web能被打包成客戶(hù)端,可方便調(diào)用Html5,CSS3。
2)PhoneGap,APPCan等方案針對(duì)不同平臺(tái)的WebView做了擴(kuò)展與封裝,使WebView 這個(gè)組件變成可訪問(wèn)設(shè)備本地API的強(qiáng)大瀏覽器,開(kāi)發(fā)人員在這些框架下可通過(guò)Javascript訪問(wèn)本地設(shè)備API。
但此方案也存在不足,一是性能不足,正常操作速度雖能滿(mǎn)足,但是頻繁操作則會(huì)導(dǎo)致響應(yīng)變慢;二是穩(wěn)定性以及占用資源方面存在著較大問(wèn)題,這是由于WebView組件不能很好的釋放內(nèi)存,導(dǎo)致內(nèi)存占用上升,甚至?xí)饝?yīng)用的crash。
3 React Native 出現(xiàn)的根本原因
在過(guò)去,移動(dòng)開(kāi)發(fā)中的Web與Native之爭(zhēng)基本以Native的勝利而告終,因?yàn)閃eb UI的性能無(wú)法與原生相提并論。即使目前手機(jī)性能有了巨大提升,但在UI交互等方面Web UI還是遠(yuǎn)遠(yuǎn)不如原生UI:Native 的原生控件有更好的體驗(yàn);Native有更好的手勢(shì)識(shí)別; Native有更合適的線程模型,例如圖像解碼、文本渲染仍無(wú)法多線程渲染,這影響了Web的流暢性。
這些正是直接導(dǎo)致React Native出現(xiàn)的根本原因,這也是為什么現(xiàn)在我們手機(jī)上的應(yīng)用還是基于Native的居多,目前主流應(yīng)用基本上沒(méi)有一款是用Web來(lái)實(shí)現(xiàn)的,雖然這是未來(lái)的趨勢(shì),但是現(xiàn)在而言,硬件以及軟件技術(shù)還達(dá)不到這一要求。
React Native 起源于Facebook的內(nèi)部項(xiàng)目由于其設(shè)計(jì)思想極其獨(dú)特,屬于革命性創(chuàng)新,性能出眾,代碼邏輯卻非常簡(jiǎn)單,所以被越來(lái)越多的人開(kāi)發(fā)關(guān)注和使用。
4 React Native 簡(jiǎn)介
React Native 并不能真正的解決同一份代碼,不同平臺(tái)運(yùn)行,由于Native平臺(tái)上的用戶(hù)體驗(yàn)不同,所以不提供“write once, run anywhere"解決方案,而是創(chuàng)新的提出了"Learn once, write anywhere"。即學(xué)習(xí)一次,可以在N個(gè)平臺(tái)使用。
圖1 React Native底層設(shè)計(jì)圖
由圖1可以看出應(yīng)用自下向上依次是:
1)React:不同平臺(tái)上編寫(xiě)基于React的代碼,“Learn once, write anywhere"。這部分是使用Javascript與JSX語(yǔ)法寫(xiě)的,其中JSX可以看作Javascript的拓展。使用React,可以進(jìn)行JSX與Javascript之間的切換。JSX在定義類(lèi)似Html這種樹(shù)形結(jié)構(gòu)時(shí),十分簡(jiǎn)單明了,更利于開(kāi)發(fā)和維護(hù)。
2)Virtual DOM: 相對(duì)于Browser環(huán)境下的Dom而言,Virtual Dom 是Dom基于內(nèi)存中的一種輕量極表達(dá)方式,可以通過(guò)不同的渲染引擎生成不同平臺(tái)下的UI,Javascript和Native,它們之間通過(guò)Bridge通信。其是React Native的設(shè)計(jì)核心,所有的組件Virtual Dom都是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu),只有當(dāng)它插入文檔以后,都會(huì)變成真實(shí)的Dom。而所有的Dom的變動(dòng),都是先在虛擬的Dom上發(fā)生,然后再將實(shí)際發(fā)生的變動(dòng)的部分,反應(yīng)在真實(shí)的Dom上,這種算法叫做Dom diff,它可以極大提高網(wǎng)頁(yè)的性能表現(xiàn)。
3)Web/Ios/Android: 現(xiàn)支持主流的客戶(hù)端Web、Ios、Android。
整個(gè)React 的核心思想是:封裝組件,各個(gè)組件維護(hù)自己的狀態(tài)和UI,當(dāng)狀態(tài)變更,自動(dòng)重新渲染整個(gè)組件。即將組件看成一個(gè)狀態(tài)機(jī),開(kāi)始有一個(gè)初始狀態(tài),然后用戶(hù)互動(dòng),導(dǎo)致?tīng)顟B(tài)變化,從而觸發(fā)重新渲染UI。
從原理上來(lái)說(shuō),React Native 繼承了 React.js 的虛擬 DOM 的思想,它是用虛擬的View來(lái)實(shí)現(xiàn)的。這個(gè)框架提供了一組 native 實(shí)現(xiàn)的 view (在 iOS 平臺(tái)上是 RCT 開(kāi)頭的一系列類(lèi))。在寫(xiě) JavaScript (更準(zhǔn)確地說(shuō),對(duì)于 React Native,寫(xiě)的是帶有 XML 的 JavaScript:JSX) 時(shí),通過(guò)將虛擬 View 添加并綁定到注冊(cè)的模塊中,在 native 側(cè)用 JavaScript 運(yùn)行環(huán)境 (對(duì)于 iOS 來(lái)說(shuō)也就是 JavaScriptCore) 執(zhí)行編譯并注入好的 JavaScript 代碼,獲取其對(duì) UI 的調(diào)用,將其截取并橋接到 native 代碼中進(jìn)行對(duì)應(yīng)部件的渲染。而在布局方面,依然是通過(guò) CSS 來(lái)實(shí)現(xiàn)。
正是于此,React下面的兩個(gè)特性使得它與其他框架不一樣:①可以基于React Native使用Javascript編寫(xiě)應(yīng)用邏輯,UI則可以保持全是原生。Html5的UI則不必做出妥協(xié);②React引入了一種不同的、略顯激進(jìn)但具備高可用性的方案來(lái)構(gòu)建用戶(hù)界面,使得應(yīng)用的UI可以簡(jiǎn)單通過(guò)一個(gè)基于應(yīng)用目前狀態(tài)的函數(shù)來(lái)表達(dá)。
而正是這種組件化思想與設(shè)計(jì)可以幫助開(kāi)發(fā)者封裝自己的代碼,使得開(kāi)發(fā)更加有效率。
5 React Native 交互原理
由上文可以看出,React Native的前端語(yǔ)言是JSX,由它去負(fù)責(zé)前端內(nèi)容的展示,但是有些內(nèi)容React Native本身是不能實(shí)現(xiàn)的,特別是一些第三方的接口,其沒(méi)有提供React Native接口,這就需要JSX與原生開(kāi)發(fā)進(jìn)行交互,JSX提供了一個(gè)主動(dòng)調(diào)用原生函數(shù)機(jī)制,使得其成為可能。
由圖2可以看出JSX發(fā)起通知的過(guò)程就是調(diào)用原生模塊的函數(shù),JSX和原生模塊是在兩個(gè)線程里面,JSX只是發(fā)起通知,并不會(huì)等待原生模塊執(zhí)行完函數(shù)。JSX調(diào)用原生模塊的函數(shù)式可以傳遞參數(shù)的變量類(lèi)型,與原生變量類(lèi)型是一一對(duì)應(yīng)的,這如同Java通過(guò)JNI調(diào)用C一樣。
JSX與原生的View進(jìn)行交互:React Native 呈現(xiàn)View的方式就是通過(guò)各種各樣的標(biāo)簽,使用原生View其就是把原生的View包裝成一個(gè)標(biāo)簽,而View本身的函數(shù),可以在JSX層去直接調(diào)用它們,如圖4。
因而在JSX中調(diào)用View的原理如圖5:
上面介紹了JSX是如何與原生的函數(shù)以及原生的View進(jìn)行交互,可以看出JSX始終是執(zhí)行者,通過(guò)這種方式也就解釋了React Native的:Learn once, write anywhere。
6 React Native 優(yōu)勢(shì)與劣勢(shì)
React Native 從Native開(kāi)發(fā)來(lái)說(shuō),相當(dāng)于重新發(fā)明了一個(gè)瀏覽器并且套了一個(gè)React的殼,從Web開(kāi)發(fā)角度來(lái)說(shuō),就是把原生的React的后端換成了Native code來(lái)實(shí)現(xiàn)。因而它的優(yōu)勢(shì)與劣勢(shì),就要相對(duì)于以前的這兩種框架來(lái)區(qū)分。
優(yōu)勢(shì)相對(duì)于Webapp:
1)不用WebView,徹底擺脫了WebView的交互和性能問(wèn)題。
2)有較強(qiáng)的擴(kuò)展性,這是因?yàn)镹ative端提供的是基本控件,Js可以自由組合使用。
3)可以使用Native原生的動(dòng)畫(huà),這點(diǎn)用Web非常困難。
優(yōu)勢(shì)相對(duì)于Native app:
1)可以通過(guò)更新遠(yuǎn)端Js,直接更新App。
2)組件化思想可以幫助開(kāi)發(fā)者增加效率。
而它的劣勢(shì)也是顯而易見(jiàn)的:
1)擴(kuò)展性不如Web,更不如Native方案。
2)從Native 到 Web,要做很多概念轉(zhuǎn)換,勢(shì)必造成雙方都要妥協(xié),這導(dǎo)致了React Native的門(mén)檻相對(duì)較高,學(xué)習(xí)成本較大。
3)不夠成熟與完善,由于React Native發(fā)展時(shí)間比較短,在使用過(guò)程中遇到問(wèn)題不如原生開(kāi)發(fā),能比較快速的找到解決方案,這需要用戶(hù)自己花費(fèi)較多時(shí)間解決問(wèn)題。
7 總結(jié)
React Native是以把React編程模式的能力帶到移動(dòng)開(kāi)發(fā)來(lái)作為主要目標(biāo)。它的目標(biāo)不是跨平臺(tái)一次編寫(xiě)到處執(zhí)行,而是一次學(xué)習(xí)跨平臺(tái)開(kāi)發(fā)。
但對(duì)Web前端來(lái)說(shuō),React 是一個(gè)全新的領(lǐng)域,需要我們來(lái)完成配套的基礎(chǔ)設(shè)施,就如中國(guó)的淘寶已經(jīng)上線相關(guān)應(yīng)用,需要我們廣大開(kāi)發(fā)者與教育者來(lái)共同推進(jìn)業(yè)界進(jìn)步。
Web是未來(lái),Native是當(dāng)下,而React Native是在未來(lái)與當(dāng)下之間。
參考文獻(xiàn):
[1] FaceBook office.A JavaScript library for building user interfaces | React [EB/OL].[2013-05].http://facebook.github.io/react/.
[2] Sebastian Markb?ge. React (Virtual) DOM Terminology[EB].[2014-06].
[3] Jack Callister. The React Quick Start Guide[EB/OL]. [2015-01]. http://www.jackcallister.com/2015/01/05/the-react-quick-start-guide.html.
[4] 阮一峰. React 入門(mén)實(shí)例教程[EB/OL].[2015-03-31]. http://www.ruanyifeng.com/blog/2015/03/react.html.