React Native學習

React Native

1.React Native之了解

1.1 Native開發(fā)優(yōu)勢:

  • Native的原生控件有更好的體驗;
  • Native有更好的手勢識別思恐;
  • Native有更合適的線程模型驶俊,盡管Web Worker可以解決一部分問題,但如圖像解碼摧莽、文本渲染仍無法多線程渲染医寿,這影響了Web的流暢性。

1.2 React Native優(yōu)勢:

  • 1.既擁有Native的用戶體驗盈咳、又保留React的開發(fā)效率(RN通過JavaScript Core解析JavaScript模塊耿眉,轉換成原生Native組件渲染)
  • 2.React Native基本完成了對多端的支持,可以靈活的使用HTML和CSS布局,使用React語法構建組件,實現(xiàn):H5, Android, iOS多端代碼的復用
  • 3.追求極致的用戶體驗:實時熱部署(CodePush在修復一些小問題和添加新特性的時候猪贪,不需要經(jīng)過二進制打包跷敬,可以直接推送代碼進行實時更新讯私。)
  • 4.UI排版的問題:
    類似HTML + CSS的排版使用原生控件渲染的框架:
    BeeFramework,BeeFramework雖然開源多年热押,而且有2000多的star數(shù),但是受限于它自身的影響力以及框架的復雜性斤寇,一直沒有很大的成功桶癣。
    React Native采用了類似HTML + CSS的排版,可以內嵌到模塊,也可以全局使用娘锁,定義樣式變得非常簡單通用牙寞。引入了Flexbox布局,使用很方便莫秆,學習起來也更簡單间雀。
  • 5.動態(tài)綁定,這個React的基本功能镊屎,被帶到了客戶端開發(fā)中來惹挟,數(shù)據(jù)和視圖是動態(tài)綁定的,數(shù)據(jù)發(fā)生變化缝驳,視圖會跟著變化连锯,很多操作視圖的代碼都可以省略了归苍。
  • 6.引入了方便的npm管理,有大量現(xiàn)成的nodejs包可以用(例如moment运怖,underscore等常用模塊)滔岳,還可以把自己項目模塊搞到內部npm上做通用組件远舅,另外,npm上還有不少別人寫的react native的插件。
  • 7.第三方組件里有一個可以把icon font引入項目的組件茧痕,可以在任何顯示圖標的地方直接用icon font顯示
  • 8.調試很方便,一次編譯后喊递,每次改了js代碼冰垄,只需要在模擬器里command+R即可重新加載代碼。有問題會直接報錯捻勉,里面有代碼行數(shù)等詳細信息镀梭。
  • 9.完整封裝了各種js內置的方法,例如:setTimeout踱启,setInterval报账,XMLHttpRequest,localstorage埠偿,console.log等透罢,都是用oc原生方法封裝的。
  • 10.引入ES6的支持冠蒋,可以使用各種新特性羽圃,例如最常用的箭頭函數(shù),解決this作用域亂套的問題抖剿。

1.3 React Native是什么?

基本概念
基本概念

Facebook于2015年9月15日發(fā)布React Native
廣大開發(fā)者可以使用JavaScript和React開發(fā)跨平臺移動應用.
React Native提倡組件化開發(fā):即提供一個個封裝好的組件朽寞,組件相互嵌套形成新的組件

1.4 React Native開發(fā)注意事項

目前react native在iOS上僅支持iOS8以上,Android僅支持Android4.1以上版本斩郎;
由于React Native的版本更新速度很快脑融,如果沒有深厚的JavaScript基礎,建議選擇:
功能適中缩宜,交互一般肘迎,不需要特別多的系統(tǒng)原生支持;
對于部分復雜的應用锻煌,可以考慮原生+React Native混合開發(fā)

1.5 React Native開發(fā)環(huán)境:

參考中文React Native網(wǎng)站:
React Native開發(fā)環(huán)境配置

2.React Native之學習

2.1 FlexBox布局:

彈性盒模型(The Flexible Box Module),又叫Flexbox妓布,意為“彈性布局”,旨在通過彈性的方式來對齊和分布容器中內容的空間宋梧,使其能適應不同屏幕匣沼,為盒裝模型提供最大的靈活性。
Flex布局主要思想是:讓容器有能力讓其子項目能夠改變其寬度乃秀、高度(甚至是順序)肛著,以最佳方式填充可用空間圆兵;
Flex學習入門網(wǎng)站:Flex布局教程
flex基本概念:

flex基本概念

  • 采用Flex布局的元素,稱為Flex容器(flex container)枢贿,簡稱"容器"殉农。它的所有子元素自動成為容器成員,稱為Flex項目(flex item)局荚,簡稱"項目"超凳。
  • 容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start耀态,結束位置叫做main end轮傍;交叉軸的開始位置叫做cross start首装,結束位置叫做cross end创夜。
  • 項目默認沿主軸排列。單個項目占據(jù)的主軸空間叫做main size仙逻,占據(jù)的交叉軸空間叫做cross size驰吓。
  • flex常用屬性總結:
  • 容器屬性:
    flex-direction(主軸方向)
    flex-wrap(是否換行)
    justify-content(item在主軸對齊方式) ,
    align-items(item在交叉軸上如何對齊) ,
  • 元素屬性:
    Flex:彈性寬度:寬度=item該flex值/該容器所有item的flex和*(容器寬度-該容器item沒有設置flex的直接寬度)
    align-self:性允許單個項目有與其他項目不一樣的對齊方式,可覆蓋align-items屬性

2.2 Touchable系列組件:

  • 高亮觸摸TouchableHighlight:
    當手指點擊按下的時候系奉,該視圖的不透明度會進行降低同時會看到相應的顏色檬贰,其實現(xiàn)原理則是在底層新添加了一個View。TouchableHighlight只能進行一層嵌套缺亮,不能多層嵌套翁涤。
  • 常用屬性:
    activeOpacity number設置組件在進行觸摸的時候,顯示的不透明度(取值在0-1之間)
    onHideUnderlay function方法當?shù)讓颖浑[藏的時候調用
    onShowUnderlay function方法當?shù)讓语@示的時候調用
    style可以設置控件的風格演示萌踱,該風格演示可以參考View組件的style
    underlayColor當觸摸或者點擊控件的時候顯示出的顏色
  • 不透明觸摸TouchableOpacity
    該組件封裝了響應觸摸事件葵礼;當點擊按下的時候,該組件的透明度會降低虫蝶。等等
代碼示例
style={styles.button}
source={require('./button.png')}
/>
style={styles.button}
source={require('image!myButton')}
/>

2.3組件生命周期:

基本概念
基本概念
  • 一:實例化階段函數(shù)分析:
1,getDefaultProps

初始化一些默認的屬性章咧,通常會將固定的內容放在這個函數(shù)中進行初始化和賦值;
可以利用this.props獲取組件在這里初始化它的屬性能真,組件自己不可以自己修改props(即:props可認為是只讀的)

2,getInitialState

用于對組件的一些狀態(tài)進行初始化;在以后的過程中扰柠,會再次調用粉铐,所以可以將控制控件的狀態(tài)的一些變量放在這里初始化,如控件上顯示的文字卤档,可以通過this.state來獲取值蝙泼,通過this.setState來修改state值,一旦調用了this.setState方法,組件一定會調用render方法劝枣,React框架會自動根據(jù)DOM的狀態(tài)來判斷是否需要真正的渲染汤踏。

3,componentWillMount

相當于OC中的ViewWillAppear方法.

4,render

render是一個組件中必須有的方法织鲸,本質上是一個函數(shù),并返回JSX或其他組件來構成DOM溪胶,和Android的XML布局類似搂擦,注意:只能返回一個頂級元素;可通過this.state和this.props數(shù)據(jù)。

5,componentDidMount

在調用了render方法后一般會在這個函數(shù)中處理網(wǎng)絡請求等加載數(shù)據(jù)的操作哗脖;因為UI已經(jīng)成功被渲染出來瀑踢,所以放在這個函數(shù)里進行請求操作,不會出現(xiàn)UI上的錯誤才避。

  • 二,存在期階段函數(shù)功能分析:
componentWillReceiveProps

指父元素對組件的props或state進行了修改

shouldComponentUpdate

一般用于優(yōu)化橱夭,可以返回false或true來控制是否進行渲染

componentWillUpdate

組件刷新前調用,類似componentWillMount

componentDidUpdate

更新后的hook

  • 三桑逝、銷毀期階段函數(shù)功能分析:
    用于清理一些無用的內容棘劣,如:點擊事件Listener,只有一個過程:componentWillUnmount

2.4請求網(wǎng)絡數(shù)據(jù):

  • React Native中通常是通過Ajax (異步的JavaScript和XML)請求從服務器獲取數(shù)據(jù)楞遏,然后在componentDidMount方法中創(chuàng)建Ajax請求呈础,等到請求成功,再用this.setState方法重新渲染UI橱健。

2.5 OC, Recat Native混合開發(fā):

  • 直接在iOS項目中寫代碼就能實現(xiàn)OC,reactNative混合開發(fā),在需要引入React Native的位置引用該模塊即可
    AppDelegate.m部分代碼
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"TGMeituan"
initialProperties:nil
launchOptions:launchOptions];

index.ios.js部分代碼

AppRegistry.registerComponent('TGMeituan', () => TGMeituan);

xcode的代碼引用了index.ios.js文件中的'TGMeituan',
index.ios.js其輸出了index.ios.js定義的一個TGMeituan組件
AppDelegate.m中在合適的位置引用rootView,即可實現(xiàn)混合開發(fā)

export default class TGMeituan extends Component {
       render() {
                  return ();
       }
}

2.6 ES5和ES6的React Native差異化:

  • 區(qū)別1:創(chuàng)建組件




    組件是一個自定義的js對象而钞,在es5中使用React.createClass();在es6中必須繼承React.component拘荡,

  • 區(qū)別2:組件的屬性props




    在ES6中臼节,其為屬性:defaultProps(可以標識static定義在class內,也可以定義在class外)珊皿,而在ES5中网缝,其為方法:getDefaultProps: function(){return {name:value}};

  • 區(qū)別3:組件的狀態(tài)state




    上圖左為ES5 ,右為ES6

2.7 React Native不足:

組件不全,第三方組件也不全蟋定,遇到某些特殊功能粉臊,需要搗鼓很久,例如攝像相關的驶兜,文件讀寫扼仲,文件上傳之類的組件。
性能并非媲美原生抄淑,還是有一些損耗的屠凶,特別是交換大數(shù)據(jù)的時候,例如讀取相冊肆资。
ios和android代碼并非通用矗愧,有可能會需要維護兩套,或者在代碼內做一些判斷郑原。
并非網(wǎng)上大家說的唉韭,寫一次代碼夜涕,多端通用,網(wǎng)頁版和客戶端版完全不是一個概念属愤,只有部分代碼可重用女器。
把代碼都打包到bundle里面,不知道蘋果對這種開發(fā)方式是否會不太喜歡春塌,甚至拒絕上線晓避。
打包出來的JSBundle過大;
首次進入RN頁面加載緩慢只壳;
穩(wěn)定性不夠俏拱,有大量因為RN導致的Crash:
iOS的Crash,基本都來自RCTFatalException吼句,都是RCTFatal拋出錯誤信息所知锅必,處理也相對簡單,設置自己的Error Handler即可惕艳。
void RCTSetFatalHandler(RCTFatalHandler fatalHandler);
大數(shù)據(jù)量時ListView加載卡頓搞隐。

3.ListView重用優(yōu)化

3.1 ListView不能重用的原因

首先RN的ListView其實是基于RN的RCTScrollView來實現(xiàn)的。它也實現(xiàn)了類似UIKit中通過DataSource來控制數(shù)據(jù)远搪,以及是否要做一些界面的刷新



這個View會有一個RCTView會引用它劣纲。當這個View被移出屏幕之外,再觀察他的內存引用時谁鳍,它就只被RCTUIManager引用了:
RN為了能夠保持一定的UI上的性能癞季,他用UImanager來管理所有的UI元素,只要創(chuàng)建過的倘潜,還有可能被顯示在界面上的東西绷柒,他都用這個UImanager來去管理,從而在進行Dom Diff時能夠減少View的創(chuàng)建和銷毀涮因。

3.2 ListView多做了什么废睦?

然后,我們再來看看ListView本身比RCTScrollView多做的哪些東西养泡,首先ListView包含兩個屬性—- initialListSize和pageSize嗜湃,initialListSize決定了第一屏加載item的數(shù)量,pageSize則是當你需要加載更多的時候瓤荔,每次需要載入多少的item净蚤,這樣做的主要目的在盡量減少你手機加載第一屏時所需要的時間。
還有就是它還實現(xiàn)了從JS端實現(xiàn)了Section Header输硝,Header,F(xiàn)ooter的封裝程梦,以及實現(xiàn)了監(jiān)聽onScroll事件点把,隨著View的滾動動態(tài)的添加row view橘荠。

3.3那么ListView相當于UITableView少了一點什么呢?

怎么沒有提到復用郎逃?


我們先看一下iOS的JS哥童,JS里面只有一行代碼

module.exports = require('ScrollView');

3.4 ListView性能優(yōu)化解決方案

Bridge一個UITableView

在RN中我們要bridge一個RN的View組件,我們需要實現(xiàn)RCTComponent這個protocol褒翰,這里有兩個很重要的方法

- (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex;
- (void)removeReactSubview:(id)subview;
這兩個方法是RN做Dom Diff的關鍵

什么是Dom Diff呢
在界面發(fā)生變化前贮懈,界面存在一個Dom Tree,發(fā)生業(yè)務變化之后是另外一個Dom tree优训,Tree中的每個元素都有自己的引用值朵你,Diff其實就是找出兩個Tree的差異點來確定需要進行更新的節(jié)點。最終確定一個需要插入和刪除的View的列表揣非,并通知相應的Dom節(jié)點來處理抡医。


但是RN的UI處理方式和原生對UI處理完全不一樣,我們如何Bridge一個TableView呢早敬,我們想到了一個方法忌傻。
我們創(chuàng)建一些VirtualView,他只是遵從了RCTComponent協(xié)議搞监,他其實并不是一個真正的View水孩,我把它形成一個組件,把它Bridge到JS琐驴,這就使得俘种,你在寫JSX的時候,就可以直接用VirtualView來去做布局了棍矛。在RN里面做布局的時候我們用VirtualView來做布局安疗。但是最終在insertReactSubview時,我們把這些VirtualView當做數(shù)據(jù)去處理够委,通過VirtualView和RealView的對應關系荐类,把它轉化成一個真實的View對象添加到TableView中去。
用這個圖來說茁帽,更清晰一些玉罐。


首先我們寫的是一個JSX,React把它轉化成Dom Tree潘拨,在進行Dom Diff后吊输,React會調用insertReactSubview傳入VirtualView,我們通過VirtualView生成Tree Data铁追,
通過VirtualView和RealView的對應關系季蚂,我們創(chuàng)建RealView去真正的添加到原生的View上。
但是這里又產(chǎn)生另外一個問題,大家會自定義一個cell的一個對象來去做的扭屁。這個對象算谈,能夠接收你特定的數(shù)據(jù),對這個cell重新去set一些控件的值料滥,然后把界面更新然眼。
但是在JS里面我們并沒有辦法這樣做,在RN中葵腹,我們不可能動態(tài)的去往Native里面去加一個類高每。
那么我們是如何做到,在復用的時候對于Cell上面的子View能夠去設置更新他的數(shù)據(jù)践宴?


我們在所有子view上面我們也加上了tag屬性鲸匿,在更新數(shù)據(jù)的時候我們通過tag找到更新的子view上面的view對他做數(shù)據(jù)的更新的。所以并不是只有Cell有這樣的tag浴井,包括子view也會有這樣的tag晒骇,這樣就做到了可以獲取到對應tag的子view并對子view的數(shù)據(jù)進行更新。


最后磺浙,為了客戶端的同學在使用這個TableView時更好上手一些洪囤,我們把幾乎整套的TableViewDataSource方法,全部照搬到了RN中撕氧,所以我們在創(chuàng)建這個ListView的時候我們需要去設置很多的回調方法瘤缩,這樣做也是為了能夠更快的做一些界面的遷移工作。

3.5 ListView性能優(yōu)化解決方案的缺點

首先既然它需要做映射伦泥,我們肯定需要做一個Virtualview到NativeView剥啤,大多數(shù)的cell里面如果做展示來用的話,Label和Image基本上能夠滿足大多數(shù)的需求了不脯。所以我們現(xiàn)在只是做了Label和Image的對應工作府怯,但在RN的一些官方控件,在這個view里面都是沒法直接使用的防楷。
還有一個缺點就是說牺丙,因為我們是按照TableView的邏輯去做的,這個邏輯其實在Android上可能不適用复局,因為Android的ListView實現(xiàn)跟iOS完全不是一個邏輯冲簿,導致使用這個ListView的RN代碼,可能沒法直接應用到Android里面去亿昏。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末峦剔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子角钩,更是在濱河造成了極大的恐慌吝沫,老刑警劉巖呻澜,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異野舶,居然都是意外死亡易迹,警方通過查閱死者的電腦和手機宰衙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門平道,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人供炼,你說我怎么就攤上這事一屋。” “怎么了袋哼?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵冀墨,是天一觀的道長。 經(jīng)常有香客問我涛贯,道長诽嘉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任弟翘,我火速辦了婚禮虫腋,結果婚禮上,老公的妹妹穿的比我還像新娘稀余。我一直安慰自己悦冀,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布睛琳。 她就那樣靜靜地躺著盒蟆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪师骗。 梳的紋絲不亂的頭發(fā)上历等,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音辟癌,去河邊找鬼寒屯。 笑死,一個胖子當著我的面吹牛愿待,可吹牛的內容都是我干的浩螺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼仍侥,長吁一口氣:“原來是場噩夢啊……” “哼要出!你這毒婦竟也來了?” 一聲冷哼從身側響起农渊,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤患蹂,失蹤者是張志新(化名)和其女友劉穎或颊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體传于,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡囱挑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沼溜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片平挑。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖系草,靈堂內的尸體忽然破棺而出通熄,到底是詐尸還是另有隱情,我是刑警寧澤找都,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布唇辨,位于F島的核電站,受9級特大地震影響能耻,放射性物質發(fā)生泄漏赏枚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一晓猛、第九天 我趴在偏房一處隱蔽的房頂上張望饿幅。 院中可真熱鬧,春花似錦鞍帝、人聲如沸诫睬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摄凡。三九已至,卻和暖如春蚓曼,著一層夾襖步出監(jiān)牢的瞬間亲澡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工纫版, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留床绪,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓其弊,卻偏偏與公主長得像癞己,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子梭伐,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內容

  • React Native學習<一> 認識Recat Native 博客原文:http://www.jianshu....
    AFinalStone閱讀 2,668評論 0 12
  • 本指南匯集React-Native各類學習資源痹雅,給大家提供便利。指南正在不斷的更新糊识,大家有好的資源歡迎Pull R...
    熊凱閱讀 5,564評論 1 62
  • 作者:ele828原文地址:https://github.com/ele828/react-native-guid...
    IT程序獅閱讀 45,473評論 17 380
  • 三個月零一天贮尉,是我們在一起的一半時間,也是你離開我的時間朴沿。說實話猜谚,我早就清楚了為什么我們會走散,但是我始終不愿意相...
    摳腳霸王花閱讀 587評論 0 1
  • 我好幼稚悯仙,是我幼稚我不好龄毡,沒有你們的高端大氣上檔次,也沒有你們的低調奢華有內涵 锡垄,我他媽的只是一普通人,我他媽的也...
    幕語閱讀 179評論 0 0