探究react-native組件的渲染過程與生命周期

我們知道React Native之所以能在移動(dòng)設(shè)備上運(yùn)行起來恬总,是因?yàn)镽eact Native和原生設(shè)備之間有一種交互前普,以iOS為例,React Native 能夠運(yùn)行起來壹堰,全靠 objective-c 和 JavaScript 的交互拭卿。對于頁面的渲染來說,React的渲染都是以組件為單位贱纠,那么這個(gè)React組件到底是怎么用原生組件渲染的呢峻厚?
<h2>React組件的產(chǎn)生過程與生命周期</h2>
<h4>ReactElement</h4>
用于描述虛擬節(jié)點(diǎn),它們可以通過 React.createElement 方法或 jsx 寫法被創(chuàng)建。
ReactElement分為 DOM Element 和 Component Elements 兩類谆焊,前者是dom組件后者是自定義組件如

class MyText extends React.Component {
  render() {
    ...
   }
}

<h4>初始化過程</h4>
上一張圖

1.通過render()方法惠桃,將element的虛擬根節(jié)點(diǎn)渲染到container中
2.接下來根據(jù)element的類型分成三種情況,String還是ReactElement中的DOM Element或Component Elements 辖试,依次實(shí)例化ReactDOMTextComponent , ReactDOMComponent , ReactCompositeComponent 類
3.ReactDOMTextComponent , ReactDOMComponent , ReactCompositeComponent 用于管理 ReactElement ,負(fù)責(zé)將不同的 ReactElement 轉(zhuǎn)化成DOM辜王,并更新DOM

<h4>生命周期</h4>
當(dāng)組件按上文方式初始化后,就有了生命周期



生命周期中的每個(gè)階段都有相應(yīng)的回調(diào)函數(shù)罐孝,用于控制和操作組件呐馆。
<h5>初始化階段</h5>
圖中最上面的框
<b>getDefaultProps</b>和<b> getInitialState </b>
用于初始化組件的屬性和狀態(tài)
<b>componentWillMount</b>
在第一次繪制 render() 之前觸發(fā),在整個(gè)生命周期中只被觸發(fā)一次莲兢。
<b>componentDidMount</b>
在第一次繪制 render()之后觸發(fā)汹来,在整個(gè)生命周期中只被觸發(fā)一次。這個(gè)函數(shù)之后改艇,就進(jìn)入了穩(wěn)定運(yùn)行狀態(tài)收班,等待事件觸發(fā)。

<h5>運(yùn)行階段</h5>
<b>componentWillReceiveProps</b>
組件收到新的屬性(props)時(shí)觸發(fā)谒兄,輸入?yún)?shù) nextProps 是即將被設(shè)置的屬性摔桦,舊的屬性還是可以通過 this.props 來獲取。常在此處通過調(diào)用 this.setState() 來更新的組件狀態(tài)舵变。
<b> shouldComponentUpdate </b>
組件接收到新的屬性和狀態(tài)改變的話酣溃,都會(huì)觸發(fā),輸入?yún)?shù) nextProps 和上面的 componentWillReceiveProps 函數(shù)一樣纪隙, nextState 表示組件即將更新的狀態(tài)值赊豌。這個(gè)函數(shù)的返回值決定是否需要更新組件,如果 true 表示需要更新绵咱,繼續(xù)走后面的更新流程碘饼。否者,則不更新。
<b> componentWillUpdate </b>
更新渲染前調(diào)用,輸入?yún)?shù)與 shouldComponentUpdate 一樣,但不要在此更新狀態(tài)
<b> componentDidUpdate </b>
更新渲染后調(diào)用艾恼,

<h5>卸載階段</h5>
<b> componentWillUnmount </b>
組件要被從界面上移除的時(shí)候住涉,就會(huì)觸發(fā)。一般在次進(jìn)行一些清理計(jì)時(shí)器之類的結(jié)尾工作

<h2>怎樣用原生組件渲染的</h2>
既然React Native能在移動(dòng)設(shè)備上運(yùn)行钠绍,那么上述的react組件是怎么用原生組件渲染的呢舆声?

<h4>react-native應(yīng)用的啟動(dòng)過程</h4>
<b>1.Native的初始化</b>
以ios為例,包括
讀取 JavaScript 源碼
初始化模塊信息
初始化 JavaScript 代碼的執(zhí)行器柳爽,即 RCTJSCExecutor 對象
生成模塊列表并寫入 JavaScript 端
執(zhí)行 JavaScript 源碼
這五個(gè)階段媳握,這里不是本文的描述點(diǎn),所以略過磷脯。這個(gè)地方和react-native的通訊機(jī)制打算在之后深入探討學(xué)習(xí)蛾找。
<b>2.Native端執(zhí)行初始化React上下文</b>
調(diào)用JS端AppRegistry.runApplication(key,params),key為模塊/組件名稱.
<b>3.JS端找到注冊的對應(yīng)啟動(dòng)組件赵誓,執(zhí)行renderApplication渲染整個(gè)應(yīng)用</b>
renderApplication會(huì)執(zhí)行如下代碼

ReactNative.render(
  <AppContainer>
    <RootComponent
      {...initialProps}
      rootTag={rootTag}
    />
  </AppContainer>,
  rootTag
);

其中AppContainer是一個(gè)JS組件打毛,使用View包裹了根組件,開發(fā)時(shí)工具Inspector俩功、YellowBox都是在這個(gè)組件中加載幻枉,RootComponent是傳入的根組件。
<b>4.找到j(luò)s端注冊的組件</b>
js通過AppRegistry注冊組件

AppRegistry.registerComponent('MyApp', rootComponent);

<b>5.Native端渲染組件</b>
以ios為例

self.rctRootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                        moduleName:@"MyApp"
                                        initialProperties:nil
                                        launchOptions:nil];

位于 AppDelegate 文件中绑雄,用戶能看到的一切內(nèi)容都來源于這個(gè) RootView 展辞,所有的初始化工作也都在這個(gè)方法內(nèi)完成。
<h4>原生組件渲染</h4>
應(yīng)用啟動(dòng)的最后階段就是JS端開始渲染根組件万牺,那么其它react組件怎么用原生組件渲染的呢?我們先看render()方法做了什么

render() {

    return (
          <Image source={Styles.picUrl}/>
    )
}

將jsx翻譯一下就是

render() {

    return (
            React.createElement(Image, { source: Styles.picUrl })
    )
}

回想一下上文中ReactElement的描述

ReactElement.createElement = function (type, config, children){ ... }

在react-native下ReactNative的UI組件通過requireNativeComponent -> createReactNativeComponentClass -> ReactNativeBaseComponent下mountComponent的調(diào)用關(guān)系洽腺,最終在mountComponent中調(diào)用UIManager組件創(chuàng)建View

UIManager.createView(tag, this.viewConfig.uiViewClassName, nativeTopRootTag, updatePayload);

UIManager是一個(gè)NativeModule脚粟,JS端可訪問≌号螅可通過createView核无,
updateView方法來創(chuàng)建和更新View。
之后原生組件的實(shí)現(xiàn)方法藕坯,首先是Image組件JS端代碼团南,需要requireNativeComponent加載原生組件以ios為例

const RCTImageView = requireNativeComponent('RCTImageView', Image);

返回

<RCTImageView
  {...this.props}
  style={style}
  resizeMode={resizeMode}
  tintColor={tintColor}
  source={sources}
/>

這就創(chuàng)建出原生組件了,之后的事情就是js端的邏輯對原生組件進(jìn)行控制炼彪,這就是react-native的通訊機(jī)制的問題了吐根。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辐马,隨后出現(xiàn)的幾起案子拷橘,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冗疮,死亡現(xiàn)場離奇詭異萄唇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)术幔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門另萤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诅挑,你說我怎么就攤上這事四敞。” “怎么了揍障?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵目养,是天一觀的道長。 經(jīng)常有香客問我毒嫡,道長癌蚁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任兜畸,我火速辦了婚禮努释,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咬摇。我一直安慰自己伐蒂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布肛鹏。 她就那樣靜靜地躺著逸邦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪在扰。 梳的紋絲不亂的頭發(fā)上缕减,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音芒珠,去河邊找鬼桥狡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛皱卓,可吹牛的內(nèi)容都是我干的裹芝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼娜汁,長吁一口氣:“原來是場噩夢啊……” “哼嫂易!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起存炮,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤炬搭,失蹤者是張志新(化名)和其女友劉穎蜈漓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宫盔,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡融虽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灼芭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片有额。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彼绷,靈堂內(nèi)的尸體忽然破棺而出巍佑,到底是詐尸還是另有隱情,我是刑警寧澤寄悯,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布萤衰,位于F島的核電站,受9級特大地震影響猜旬,放射性物質(zhì)發(fā)生泄漏脆栋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一洒擦、第九天 我趴在偏房一處隱蔽的房頂上張望椿争。 院中可真熱鬧,春花似錦熟嫩、人聲如沸秦踪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椅邓。三九已至,卻和暖如春昧狮,著一層夾襖步出監(jiān)牢的瞬間希坚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工陵且, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人个束。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓慕购,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茬底。 傳聞我的和親對象是個(gè)殘疾皇子沪悲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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

  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記阱表,個(gè)人覺得該教程講解深入淺出殿如,比目前大...
    leonaxiong閱讀 2,813評論 1 18
  • React Native優(yōu)秀博客贡珊,以及優(yōu)秀的Github庫列表(很多英文資料源自于[awesome-react-n...
    董董董董董董董董董大笨蛋閱讀 10,596評論 4 162
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,756評論 25 707
  • 今天早上看到各大頭條爆出男演員喬任梁在自家別墅死亡的消息,不是他殺涉馁。據(jù)了解極大可能是抑郁癥導(dǎo)致的自殘致死门岔。影視圈很...
    冰天落落閱讀 231評論 0 2
  • 一個(gè)人上班,一個(gè)人下班烤送,一個(gè)人買菜寒随,一個(gè)人做飯,一個(gè)人吃飯帮坚,一個(gè)人坐車妻往,一個(gè)人走路,一個(gè)人逛街试和,一個(gè)人shoppi...
    木子蟲閱讀 233評論 0 0