RN的大體認(rèn)識

初識React Native

我們都知道React是一套開源JavaScript 庫(也可以稱為前端 UI 框架),而React Native則是React向移動端的延伸。我們可以認(rèn)為React Native分為兩層,React 層是一套JavaScript 庫;Native層則扮演橋梁的功能,根據(jù)平臺不同映射為不同的原生控件;通過這種設(shè)計(jì)實(shí)現(xiàn)了—開發(fā)者構(gòu)建的RN代碼可以在不同的平臺上(Android和IOS)運(yùn)行,也就是Learn once, write anywhere。Java(Write once, run anywhere)

RN是如何解決H5性能瓶頸的?

首先我們需要了解H5性能瓶頸是怎么造成的?對比原生,H5包含信息更加自由豐富,這也導(dǎo)致:
1、從服務(wù)器獲取信息時候,H5頁面需要更多的數(shù)據(jù)量和校驗(yàn)步驟,相應(yīng)的需要消耗更多的時間;
2、本地解析渲染(顯示)時候,H5需要更復(fù)雜的解析渲染規(guī)則,相應(yīng)的需要耗費(fèi)更多的時間。

RN可以認(rèn)為是H5(JS)的特殊子集合。那么RN解決H5性能瓶頸,自然也是從這兩點(diǎn)進(jìn)行出發(fā)的。
首先我們看問題1,它關(guān)鍵在于正常使用時候減少網(wǎng)絡(luò)請求的數(shù)據(jù)量。這一點(diǎn)我們其實(shí)已經(jīng)從一個名詞( JS bundle)中猜測到,RN相當(dāng)于進(jìn)入一個模塊時候(可以自定義分包)把需要更新的的H5頁面打包成一捆(js bundle,可能是一頁,也可能是好幾頁)一次性更新,當(dāng)再次加載該頁面的時候,就直接從本地獲取就行了。在這種方式下,當(dāng)非首次加載JS bundles時候,從網(wǎng)絡(luò)請求的數(shù)據(jù)跟原生基本差不多,甚至一些特定情況比原生還要少。所以問題1的答案就是是運(yùn)用(批量)緩存的方式來減少平時使用過程中網(wǎng)絡(luò)請求數(shù)據(jù)量。
接下來我們再研究問題2,它關(guān)鍵在于縮短JS代碼解析渲染的時間,為解決這個問題,F(xiàn)acebook采用了兩個重要舉措:
1、引入虛擬DOM減少不必要的渲染;

虛擬DOM、虛擬硬盤、虛擬機(jī)等計(jì)算機(jī)術(shù)語中提到的“虛擬”基本都是為了解決“真實(shí)”操作起來復(fù)雜、繁瑣、代價(jià)高等問題而生,它們都能夠?qū)⑾鄬唵畏奖愕奶摂M操作映射成為真實(shí)的行動。虛擬DOM的出現(xiàn)之前,一次頁面更新可能有十幾個DOM更新操作,前前后后更新了十幾次,大大浪費(fèi)了渲染性能。出現(xiàn)虛擬DOM之后,一次更新操作中的10次更新DOM的動作,不會立即操作DOM,而是將這10次更新更新到虛擬DOM中,通過對比找出前后兩次虛擬DOM的不同(diff算法),然后把不同一次性映射為真實(shí)DOM的更新。

2、舍棄JS渲染,通過映射的方式把RN代碼中的控件一個個映射為原生控件進(jìn)行渲染。

由于JS的靈活性與復(fù)雜性,雖然很多團(tuán)隊(duì)在研究它的渲染問題,但它的解析+渲染始終比原生慢上許多。于是facebook工程師另辟蹊徑,它認(rèn)為既然原生渲染快,那就用原生渲染代替JS渲染,RN做好橋接就好了。比如我們用RN代碼寫一個Button,那么實(shí)際在運(yùn)行的時候RN會生成一個映射表,將這個Button分別映射為android和ios的button,相關(guān)設(shè)置的屬性也進(jìn)行了同步映射。

兩個很重要的概念

Props(屬性)

大多數(shù)組件在創(chuàng)建時就可以使用各種參數(shù)來進(jìn)行定制。用于定制的這些參數(shù)就稱為props(屬性)。
以常見的基礎(chǔ)組件Image為例,在創(chuàng)建一個圖片時,可以傳入一個名為source的prop來指定要顯示的圖片的地址,以及使用名為style的prop來控制其尺寸。

比如Android里的Activity的話,Props有點(diǎn)類似Intent ,props是在父組件中指定,而且一經(jīng)指定,在被指定的組件的生命周期中則不再改變。但是功能比Intent 強(qiáng)大,

State(狀態(tài))

我們使用兩種數(shù)據(jù)來控制一個組件:props和state。props是在父組件中指定,而且一經(jīng)指定,在被指定的組件的生命周期中則不再改變。 對于需要改變的數(shù)據(jù),我們需要使用state。
一般來說,你需要在constructor中初始化state(譯注:這是ES6的寫法,早期的很多ES5的例子使用的是getInitialState方法來初始化state,這一做法會逐漸被淘汰),然后在需要修改時調(diào)用setState方法。

相同點(diǎn)

  1. 不管是props還是state的改變,都會引發(fā)render的重新渲染。
  2. 都能由自身組件的相應(yīng)初始化函數(shù)設(shè)定初始值。

不同點(diǎn)

  1. 初始值來源:state的初始值來自于自身的getInitalState(constructor)函數(shù);props來自于父組件或者自身getDefaultProps(若key相同前者可覆蓋后者)。
  2. 修改方式:state只能在自身組件中setState,不能由父組件修改;props只能由父組件修改,不能在自身組件修改。
  3. 對子組件:props是一個父組件傳遞給子組件的數(shù)據(jù)流,這個數(shù)據(jù)流可以一直傳遞到子孫組件;state代表的是一個組件內(nèi)部自身的狀態(tài),只能在自身組件中存在。

生命周期

我們先來看初始化,在初始化的過程中,會按順序調(diào)用下面5個函數(shù)。

getDefaultProps:組件實(shí)例創(chuàng)建前調(diào)用,多個實(shí)例間共享引用。注意:如果父組件傳遞過來的Props和你在該函數(shù)中定義的Props的key一樣,將會被覆蓋。
getInitalState:組件示例創(chuàng)建的時候調(diào)用的第一個函數(shù)。主要用于初始化state。注意:為了在使用中不出現(xiàn)空值,建議初始化state的時候盡可能給每一個可能用到的值都賦一個初始值。
componentWillMount:在render前,getInitalState之后調(diào)用。僅調(diào)用一次,可以用于改變state操作。
render:組件渲染函數(shù),會返回一個Virtual DOM,只允許返回一個最外層容器組件。render函數(shù)盡量保持純凈,只渲染組件,不修改狀態(tài),不執(zhí)行副操作(比如計(jì)時器)。
componentDidMount:在render渲染之后,React會根據(jù)Virtual DOM來生成真實(shí)DOM,生成完畢后會調(diào)用該函數(shù)。在瀏覽器端(React),我們可以通過this.getDOMNode()來拿到相應(yīng)的DOM節(jié)點(diǎn)。然而我們在RN中并用不到,在RN中主要在該函數(shù)中執(zhí)行網(wǎng)絡(luò)請求,定時器開啟等相關(guān)操作

初始化完成之后,組件將會進(jìn)入到運(yùn)行中狀態(tài),運(yùn)行中狀態(tài)我們將會遇到如下幾個函數(shù):

componentWillReceiveProps(nextProps):props改變(父容器來更改或是redux),將會調(diào)用該函數(shù)。新的props將會作為參數(shù)傳遞進(jìn)來,老的props可以根據(jù)this.props來獲取。我們可以在該函數(shù)中對state作一些處理。注意:在該函數(shù)中更新state不會引起二次渲染。
boolean shouldComponentUpdate(object nextProps, object nextState):該函數(shù)傳遞過來兩個參數(shù),新的state和新的props。state和props的改變都會調(diào)到該函數(shù)。該函數(shù)主要對傳遞過來的nextProps和nextState作判斷。如果返回true則重新渲染,如果返回false則不重新渲染。在某些特定條件下,我們可以根據(jù)傳遞過來的props和state來選擇更新或者不更新,從而提高效率。
componentWillUpdate(object nextProps, object nextState):與componentWillMount方法類似,組件上會接收到新的props或者state渲染之前,調(diào)用該方法。但是不可以在該方法中更新state和props。
render:跟初始化的時候功能一樣。
componentDidUpdate(object prevProps,object prevState):和初始化時期的componentDidMount類似,在render之后,真實(shí)DOM生成之后調(diào)用該函數(shù)。傳遞過來的是當(dāng)前的props和state。在該函數(shù)中同樣可以使用this.getDOMNode()來拿到相應(yīng)的DOM節(jié)點(diǎn)。如果你需要在運(yùn)行中執(zhí)行某些副操作,請?jiān)谠摵瘮?shù)中完成。componentWillReceiveProps(nextProps):props改變(父容器來更改或是redux),將會調(diào)用該函數(shù)。新的props將會作為參數(shù)傳遞進(jìn)來,老的props可以根據(jù)this.props來獲取。我們可以在該函數(shù)中對state作一些處理。注意:在該函數(shù)中更新state不會引起二次渲染。

銷毀階段只有一個函數(shù),很簡單

componentWillUnmount:組件DOM中移除的時候調(diào)用。在這里進(jìn)行一些相關(guān)的銷毀操作,比如定時器,監(jiān)聽等等。

生命周期 跳用次數(shù) 是否setState
getDefaultProps 1(全局調(diào)用一次)
getInitialState 1
componentWillMount 1
render >=1
componentDidMount 1
componentWillReceiveProps >=0
shouldComponentUpdate >=0
componentWillUpdate >=0
componentDidUpdate >=0
componentWillUnmount 1

優(yōu)勢

1、 跨平臺
2、 組件
3、 簡化的生命周期
4、 迭代的速度(高峰期)
5、 性能(出去初始化的時間的話)
6、 Redux (狀態(tài)管理的庫等)
7、 支持原生
8、 動畫
9、 開源

遇到的問題

首先,必須承認(rèn),RN不是JS工程師就可以搞定的。 不懂IOS還好, 團(tuán)隊(duì)沒有懂a(chǎn)ndroid整個架構(gòu)的工程師, android就可能有各種問題。 優(yōu)化android是一件非常繁瑣的事情,得知道優(yōu)化android需要很多的黑科技。

其次, RN也不是Native工程師可以順利搞定的。 native工程師做的時候會束手束腳,其實(shí)這和npm生態(tài)有關(guān)。 在開發(fā)native產(chǎn)品時候, 大部分需要用到的架構(gòu)library庫,都是官方搞定的。 而RN如果說, 架構(gòu)很好, 那是社區(qū)搞定的。 所以對于剛剛接觸RN的native工程師, 會覺得RN非常難以架構(gòu), 沒有架構(gòu)的工具,

而且Android技術(shù)也在不斷優(yōu)化中,就一個Databinding特性就不是ReactNative所能支持的,更別提其他的RxAndroid響應(yīng)式編程了這些東西了,涉及底層的功能需要Android和Ios雙端單獨(dú)開發(fā),JS調(diào)用,整體性能仍不如原生;

我覺得ReactNative更像是原生開發(fā)的一個補(bǔ)充,一些App的新的嘗試的可能。畢竟用純ReactNative開發(fā)商業(yè)化的App,我怎么都覺得有點(diǎn)不靠譜,有過Aribnb 大公司的前車之鑒

趟坑總結(jié):

同樣的代碼在Android 和IOS 的響應(yīng)速度以及請求的成功率不一樣:

TypeError: Network request failed:

https://blog.csdn.net/qq_32312317/article/details/80868118

**react-native link XX **

react-native 并不成熟

React Native比Android或iOS更不成熟(或者說是穩(wěn)定)。 它更新,更有野心,并且更新速度非常快。 雖然React Native在大多數(shù)情況下都能很好地工作,但有些情況下,它的不穩(wěn)定可能會顯示出來,并且會使原生開發(fā)中的一些微不足道的事情變得非常困難。 不幸的是,這些情況很難預(yù)測,可能需要幾小時到幾天的時間才能解決。這個問題,Airbnb 團(tuán)隊(duì) 自行維護(hù)RN分支

由于React Native的不成熟,他們有時需要修正React Native源碼。 除了向React Native做出貢獻(xiàn)之外,他們還必須維護(hù)一個分支,以便他們能夠快速合并更改并使版本崩潰。 在過去兩年中,他們不得不在React Native之上添加大約50次提交。 這使得升級React Native的過程非常痛苦。

重構(gòu)之難

JavaScript是一種無類型的語言。 缺乏類型安全性難以擴(kuò)展,JavaScript被忽略的副作用是重構(gòu)非常困難且容易出錯。 重命名props,特別是帶有通常名稱的props,如通過多個組件傳遞的onClick或props,是準(zhǔn)確重構(gòu)的噩夢。 更糟糕的是,重構(gòu)在生產(chǎn)中而不是在編譯時崩潰,很難為其添加適當(dāng)?shù)撵o態(tài)分析。

react-native開放源代碼庫

在Android上,許多React Native庫也要求您使用node_modules的相對路徑,而不是發(fā)布與社區(qū)所期望的不一致的maven工件。 需要動態(tài)去鏈接一些庫,
RN的很多庫,需要單獨(dú)對IOS或者Aandroid 要進(jìn)行特殊的處理,但是一般給出的文檔都不是很詳細(xì)
比如 react-native-webview react-native-community/react-native-masked-view react-native link react-native-device-info 都需要去react-native link xx or pod install 原理就是將一個node_module里面的工程,作為Android的project


image.png

初始化時間

在React Native首次可以渲染之前,必須初始化其運(yùn)行時。 不幸的是,即使在高端設(shè)備上,也需要幾秒鐘的時間。 這使得使用React Native進(jìn)行啟動屏幕幾乎是不可能的。通過在應(yīng)用程序啟動時初始化React Native來縮短第一次渲染時間。與原生屏幕不同,渲染React Native需要至少一個完整的主線程 - > js - >Yoga布局線程 - >主線程往返行程,然后才有足夠的信息來第一次渲染屏幕。iOS平均初始p90呈現(xiàn)280ms,Android平均440ms。 在Android上,使用通常用于共享元素轉(zhuǎn)換的postponeEnterTransition API來延遲顯示屏幕直到它被渲染。 在iOS上,我遇到了問題,從React Native快速設(shè)置導(dǎo)航欄配置。 因此,我為所有React Native屏幕過渡添加了50ms的仿真延遲,以防止配置加載后導(dǎo)航欄閃爍。

手勢

在涉及復(fù)雜手勢的屏幕上使用React Native,因?yàn)锳ndroid和iOS的觸摸子系統(tǒng)足夠不同,以至于提出統(tǒng)一的API對整個React Native社區(qū)來說都具有挑戰(zhàn)性。需要按照不同的os 單獨(dú)設(shè)置

莫名其妙的崩潰

不得不面對一些難以解決的非常奇怪的崩潰。 例如,Hermes 引擎下,react-navigation-stack庫不支持,在官方這些文檔上并沒有體現(xiàn)出來,不支持這個的原因我也是在假設(shè),正常的代碼打成bundle 就運(yùn)行不了!

資料之難

似乎RN的已經(jīng)大勢所去,國內(nèi)外對目前版本的一些文章博客很少,github 很多優(yōu)秀的開源項(xiàng)目基本上都是三四年的,已經(jīng)很陳舊,沒有一個能順利的運(yùn)行起來


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內(nèi)容