標籤:跨平台 facebook android 行動裝置 App phonegap
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/59/85/wKioL1TW2K-BHVlgAAaGVpwHp5g726.jpg" title="react-native1浮水印.png" alt="wKioL1TW2K-BHVlgAAaGVpwHp5g726.jpg" />
React Native使用初探
February 06 2015
Facebook讓所有React Conf的參與人員都可以初嘗React Native的源碼---一個編寫原生行動裝置 App的方法。該方法運用了React.js的所有強大的功能來將其應用到原生應用。你可以通過使用其內嵌的基本元素來編寫基於Javascript的組件,這些組件都是擁有著iOS和Android控制項的支撐的。
首先,我知道Facebook現在還沒有完全將其開源是個很挫的事情啦,但他們現在正在將該項目往開源的方向推進了。他們現在正在把跟Facebook環境相關的代碼給移除掉並且正在準備建立一套接受開發人員對該開源項目進行貢獻和參與的流程。我認為他們在努力往開源這個方向推進是個很好的事情,說明他們真的很在意React社區了。相信這個項目很快就能完全開源了。
其實本人並不認為開源的步驟慢點是個根本性的錯誤了。如果你認為是的話我將很樂意跟你進行探討,但請允許我把該討論放在另外一個議題裡面吧。
因為如果你被該討論打斷思路的話,在這裡你可能會錯過我們今天對如何通過React Native編寫原生行動裝置 App的潮流已經發生改變的討論。這種改變最大的地方就是它使用起來更像是在編寫一個網路應用。
本人已經算是開發iOS應用多年的老手了,故此我有著很多原生應用開發的經驗。在跟React Native勾搭上後,我只能用以下的表情來表達我的心情:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/59/89/wKiom1TW1-7D7iBwAAI1SheeB9E789.jpg" title="jawdrop浮水印.png" alt="wKiom1TW1-7D7iBwAAI1SheeB9E789.jpg" />
相信我們都聽過各種由Javascript驅動的跨平台原生應用開發架構,比如Titanium, PhoneGap, 以及其他各種各樣的允許不同層面與原生環境進行轉化的項目。所有這些架構看起來都是比較挫的:無論你現在是想把一個網路應用程式套件裝在一個WebView裡面,或者是想要硬套HTML&CSS這套很難用來構建行動裝置 App的技術。對於後者,你幾乎無時無刻不在直面原生對象,這在效能方面來說註定就是一個失敗的嘗試。React Native就不一樣,它的布局方面其實是運行在一個獨立的線程裡面的,所以UI主線程就能如往常一樣的儘可能的空閑出來進行介面動畫等的呈現處理(它同時也提供了flexbox 來簡化布局,這可並不是所有架構都能提供出來的)。
這裡你僅僅需要淺嘗就能領略到React Native所隱藏的無限潛力。它工作起來會讓你感覺你是在做網路開發一樣的舒暢。而事實上你確是在開發著一個真實的原生應用,事實上是根本分不出來這裡面的區別的。在UI層面上,這事實上是根本沒有區別的,使用到的都是像正常一樣眩眼滑動的原生的UIViews。
這其實都是軟體工程的功勞。同時這就完全進一步的證明了一個事實就是React.js是構建一個跨平台應用的正確方式。我可以使用該方式來像編寫一個網路應用一樣來編寫一個原生應用。我們完全可以從今開始把DOM作為一個實現的細節,就好像UIViews一樣。
我不否認我是很喜歡網路編程的,但如果我們一步步的埋頭慢慢的認真檢查每一個錯誤,我們就很容易把一些重大的問題跟忽略掉。網路編程的方式來編寫應用從根本上說就是個很古怪的事情:HTML加上CSS所造成的混亂會對各種架構製造路障而不是讓它們變得更好。也許React Native會最終是一個指引你回到正確的道路上面來的正確方式。我期盼著看到它是如何讓網路編程方式變成一個更好的行動裝置 App編程方式。我們不要把它想象成一個和網路編程背道而馳的東西,而要把它想象成是一個從網路編程進入到另外一個方向的原型。
到了這裡你是否已經感覺眼花繚亂無所適從了?沒事,我將會通過樣本告訴你React Native是如何工作的!當然你可以在這裡和這裡通過視頻學到更多的這方面的知識了。
React Native使用的是iOS上的JavaScriptCore來運行Javascript(Android和其他平台將會在將來進行支援)。重要的一點是它將Javascript放在一個獨立的線程上運行(其他架構如Titanium也是這樣做的)。你使用Javascript來編寫一個控制項跟使用React.js其實沒有太大的區別,除了你應該使用的是如View和Text而非div和a之外。你將會獲得使用React產生UI組件的所有的優點(保守的說,這是非常牛X的!!!)。請謹記,JavaScript不僅僅是一門語言,它還是一個平台。存在著大量的優秀的"JS轉換"工具供你使用。
React Native將你在另外一個線程通過Javascript編寫的UI以最小數量的資料發送給UI主線程來把它橋接轉換成原生的組件。比如把一個View轉換成UIView。最贊的地方是你不需要擔心你的UI主線程的更新來現實最新的改動;你只要聲明你將需要UI基於某種狀態進行橋接轉換就行了,React使用的是一個獨特的演算法把最小量的必須的改動發送到該橋接來反映UI的變化(天地會珠海分舵註:如果你清楚增量儲存的概念的話將會很容易理解這句話)。
編寫原生UI從未如此的簡單,況且這將不會有如播放動畫卡頓等諸如此類的問題的出現,因為JS是在一個獨立於UI主線程的線程中啟動並執行。動畫播放將會比吃了瀉藥還要順暢!
基於React Native的一個OpenGL應用
我的第一個React Native應用其實並不是一個傳統的應用:我編寫的是一個波前物件模型示範應用。我個人一直對遊戲開發比較感興趣,但是我對編寫原生UI卻很反感。React Native剛好給了我一個使用編寫網頁UI的方式來編寫原生UI的方案。
我保證你將會看到大量的使用原生導航和動畫之類的傳統應用示範。我認為通過非常簡便的把React Native置身於OpenGL控制項上面來完成相應的工作是一項很酷的事情。
去把React Native整合在你的項目裡面其實是個很簡單的事情,你只需要在你的控制器種建立一個RCTRootView,然後告訴它你的JS是擺在哪裡,並把它添加到視窗上面就完成了。在我的嘗試中,我是首先建立了一個OpenGL的控制項,然後把RCTRootView作為一個子控制項添加到該控制項上面。該整合的過程是完全一個***的過程,哦,不好意思,是一個完全毫無痛苦的過程。(天地會珠海分舵註:近來被電視和路邊廣告轟炸的暈了,到處都是***之類的廣告,看到無痛兩個字就立刻神經反射的聯絡到***來了)
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/59/85/wKioL1TW2Tzgw3VWAAg-KYjQ4yk399.gif" title="react-native-demo.gif" alt="wKioL1TW2Tzgw3VWAAg-KYjQ4yk399.gif" />
你可以按下Cmd+R來立刻重新整理你的UI來現實你修改的任何更新。這裡僅僅RCTRootView會進行更新,所以我可以很容易的對ui進行修改然後重新整理ui來獲得最近的修改,而並不需要重新載入OpenGL層。
以下是一個控制項樣本,一個用來列出可用檔案清單並在其中一項被點擊後載入一個網格的ObjList控制項。這裡將會用到一個和其他任何原生應用一樣的原生的用來僅僅在控制項內部進行滾動顯示的ListView控制項,但在這裡進行使用確實一個極其簡單的事情。
var ObjList = React.createClass({ // a few methods clipped.... selectModel: function(file) { controller.loadMesh(file); }, renderRow: function(file) { return View( null, TouchableHighlight( { onPress: () => this.selectModel(file), underlayColor: ‘rgba(0, 0, 0, .6)‘ }, Text({ style: { height: 30, color: ‘white‘ }}, file) ) ); }, render: function() { var source = this.getDataSource(this.props.files); return ListView({ style: { flex: 1 }, renderRow: this.renderRow, dataSource: source }); }});
在我的App控制項裡面我有一個handlSearch方法來相應文本輸入的改變。這裡我對控制項的狀態做一些改變,一邊讓應用和ObjList控制項接受到最新的狀態改變來將最新的檔案清單給顯示出來。
handleSearch: function(e) { var text = e.nativeEvent.text; var files = allFiles.filter(x => x.indexOf(text.toLowerCase()) !== -1); this.setState({ files: files });}
請注意ObjList控制項裡面的controller.loadMesh()這個調用。這其實是一個Objective-C的一個方法,這裡我已經把它做了一個匯出標識了,這樣橋接就會找到它並使它在JS中變成可用。跟橋接進行協同工作其實是一個非常簡單的事情,且將會變得越來越簡單。以下就是loadMesh的實現代碼:
- (void)loadMesh:(NSString *)path { RCT_EXPORT(); dispatch_async(dispatch_get_main_queue(), ^{ teapotNode_.material.diffuse = [self randomColor]; teapotNode_.wavefrontMeshA = [REMeshCache meshNamed:path]; [self reset]; });}
RCT_EXPORT()將該方法標識成使一個匯出方法(事實上在其他地方實現的對該類進行執行個體化的工作會有點多)。這些方法將會在一個獨立的線程中被調用,但是我這裡需要的使在主線程對該mesh進行載入(因為這將會把資料載入到OpenGL當中),所以這裡我網隊列中排隊了一塊運行在主線程中的代碼。
以下的視頻將會給大家一個更完整的示範:https://www.youtube.com/embed/OPFf53fdUmQ
在聲明的過程中來構建我們的UI控制項並對簡單的改變狀態所產生的事件進行相應的能力是非常的強大的,React.js一定證明了這一點。到此為止,我們突然間就到了需要對原生應用進行同樣處理的時候了。"一次學習,多平台編寫“,猶如React開發人員所倡導的。同時請查看:Facebook來教我我們如何編寫網站。
--------------完------------------
轉載請尊重原創/譯
作者:天地會珠海分舵
資源分享公眾號:techgogogo或掃描以片二維碼
本文出自 “天地會珠海分舵” 部落格,請務必保留此出處http://techgogogo.blog.51cto.com/3851580/1612779
行動裝置 App跨平台架構江湖將現終結者?速來參拜來自Facebook的React Native