React Native面試題總結(jié)

1.React Native相對(duì)于原生的ios和Android有哪些優(yōu)勢(shì)?

1.性能媲美原生APP 
2.使用JavaScript編碼,只要學(xué)習(xí)這一種語(yǔ)言 
3.絕大部分代碼安卓和IOS都能共用 
4.組件式開發(fā),代碼重用性很高 
5.跟編寫網(wǎng)頁(yè)一般,修改代碼后即可自動(dòng)刷新,不需要慢慢編譯,節(jié)省很多編譯等待時(shí)間 
6.支持APP熱更新,更新無(wú)需重新安裝APP

2.React Native組件的生命周期

React組件生命周期

3.當(dāng)你調(diào)用setState的時(shí)候,發(fā)生了什么事?

當(dāng)調(diào)用setState 時(shí),React會(huì)做的第一件事情是將傳遞給setState 的對(duì)象合并到組件的當(dāng)前狀態(tài)。 這將啟動(dòng)一個(gè)稱為和解(reconciliation)的過(guò)程。 和解(reconciliation)的最終目標(biāo)是以最有效的方式,根據(jù)這個(gè)新的狀態(tài)來(lái)更新UI。 為此,React將構(gòu)建一個(gè)新的 React 元素樹(您可以將其視為 UI 的對(duì)象表示)。 一旦有了這個(gè)樹,為了弄清 UI 如何響應(yīng)新的狀態(tài)而改變,React 會(huì)將這個(gè)新樹與上一個(gè)元素樹相比較( diff )。 通過(guò)這樣做, React 將會(huì)知道發(fā)生的確切變化,并且通過(guò)了解發(fā)生什么變化,只需在絕對(duì)必要的情況下進(jìn)行更新即可最小化 UI 的占用空間。

4.props和state相同點(diǎn)和不同點(diǎn)

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

不同點(diǎn) 1.初始值來(lái)源:state的初始值來(lái)自于自身的getInitalState(constructor)函數(shù);props來(lái)自于父組件或者自身getDefaultProps(若key相同前者可覆蓋后者)。

  • 2.修改方式:state只能在自身組件中setState,不能由父組件修改; props只能由父組件修改,不能在自身組件修改。

  • 3.對(duì)子組件:``props是一個(gè)父組件傳遞給子組件的數(shù)據(jù)流,這個(gè)數(shù)據(jù)流可以一直傳遞到子孫組件;state代表的是一個(gè)組件內(nèi)部自身的狀態(tài),只能在自身組件中存在。

5.shouldComponentUpdate 應(yīng)該做什么

其實(shí)這個(gè)問(wèn)題也是跟reconciliation有關(guān)系。 和解( reconciliation )的最終目標(biāo)是以最有效的方式,根據(jù)新的狀態(tài)更新用戶界面”。 如果我們知道我們的用戶界面(UI)的某一部分不會(huì)改變, 那么沒有理由讓 React 很麻煩地試圖去弄清楚它是否應(yīng)該渲染。 通過(guò)從 shouldComponentUpdate 返回false, React 將假定當(dāng)前組件及其所有子組件將保持與當(dāng)前組件相同

6.reactJS的props.children.map函數(shù)來(lái)遍歷會(huì)收到異常提示,為什么?應(yīng)該如何遍歷?

this.props.children 的值有三種可能:
1.當(dāng)前組件沒有子節(jié)點(diǎn),它就是undefined;
2.有一個(gè)子節(jié)點(diǎn),數(shù)據(jù)類型是object ;
3.有多個(gè)子節(jié)點(diǎn),數(shù)據(jù)類型就是array 。 系統(tǒng)提供React.Children.map()方法安全的遍歷子節(jié)點(diǎn)對(duì)象

7.redux狀態(tài)管理的流程

image

action是用戶觸發(fā)或程序觸發(fā)的一個(gè)普通對(duì)象。 reducer是根據(jù)action操作來(lái)做出不同的數(shù)據(jù)響應(yīng),返回一個(gè)新的state。 store的最終值就是由reducer的值來(lái)確定的。(一個(gè)store是一個(gè)對(duì)象, reducer會(huì)改變store中的某些值) action -> reducer -> 新store -> 反饋到UI上有所改變。

8.加載bundle的機(jī)制

要實(shí)現(xiàn)RN的腳本熱更新,我們要搞明白R(shí)N是如何去加載腳本的。 在編寫業(yè)務(wù)邏輯的時(shí)候,我們會(huì)有許多個(gè)js文件,打包的時(shí)候RN會(huì)將這些個(gè)js文件打包成一個(gè)叫index.android.bundle(ios的是index.ios.bundle)的文件,所有的js代碼(包括rn源代碼、第三方庫(kù)、業(yè)務(wù)邏輯的代碼)都在這一個(gè)文件里,啟動(dòng)App時(shí)會(huì)第一時(shí)間加載bundle文件,所以腳本熱更新要做的事情就是替換掉這個(gè)bundle文件。

9.Flex布局

采用Flex布局的元素,稱為Flex容器(flex Container),簡(jiǎn)稱”容器”。它的所有子元素自動(dòng)成為容器成員,稱為Flex項(xiàng)目(flex item),簡(jiǎn)稱”項(xiàng)目”。

image

容器默認(rèn)存在兩根軸:水平的主軸(main axis)垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點(diǎn))叫做main start,結(jié)束位置叫做main end;交叉軸的開始位置叫做cross start,結(jié)束位置叫做cross end。

項(xiàng)目默認(rèn)沿主軸排列。單個(gè)項(xiàng)目占據(jù)的主軸空間叫做main size,占據(jù)的交叉軸空間叫做cross size。

容器的屬性 以下6個(gè)屬性設(shè)置在容器上。 flex-direction屬性決定主軸的方向(即項(xiàng)目的排列方向)。 flex-wrap 屬性定義,如果一條軸線排不下,如何換行。 flex-flow屬性是flex-direction屬性和flex-wrap屬性的簡(jiǎn)寫形式。 justify-content定義了項(xiàng)目在主軸上的對(duì)齊方式。 align-items 屬性定義項(xiàng)目在交叉軸上如何對(duì)齊。align-content屬性定義了多根軸線的對(duì)齊方式。如果項(xiàng)目只有一根軸線,該屬性不起作用。

  • 1.在組件的style中指定flexDirection可以決定布局的主軸
flexDirection:'row',
flexDirection:'column',
  • 2.在組件的style中指定justifyContent可以決定其子元素沿著主軸的排列方式
justifyContent :'flex-start',
justifyContent :'center',
justifyContent :'flex-end',
justifyContent :'space-around',
justifyContent :'space-between',
  • 3.在組件的style中指定alignItems可以決定其子元素沿著次軸(與主軸垂直的軸,比如若主軸方向?yàn)閞ow,則次軸方向?yàn)閏olumn)的排列方式
alignItems: 'flex-start',
alignItems: 'center',
alignItems: 'flex-end',
alignItems: 'stretch',  

10.請(qǐng)簡(jiǎn)述 code push 的原理

code push 調(diào)用 react native 的打包命令,將當(dāng)前環(huán)境的非 native 代碼全量打包成一個(gè) bundle 文件,然后上傳到微軟云服務(wù)器(Windows Azure)。 在 app 中啟動(dòng)頁(yè)(或 splash 頁(yè))編寫請(qǐng)求更新的代碼(請(qǐng)求包含了本地版本,hashCode、appToken 等信息),微軟服務(wù)端對(duì)比本地 js bundle 版本和微軟服務(wù)器的版本,如果本地版本低,就下載新的 js bundle 下來(lái)后實(shí)現(xiàn)更新(code push 框架實(shí)現(xiàn))。

11.Redux中同步 action 與異步 action 最大的區(qū)別是什么

同步只返回一個(gè)普通 action 對(duì)象。而異步操作中途會(huì)返回一個(gè) promise 函數(shù)。當(dāng)然在 promise 函數(shù)處理完畢后也會(huì)返回一個(gè)普通 action 對(duì)象。thunk 中間件就是判斷如果返回的是函數(shù),則不傳導(dǎo)給 reducer,直到檢測(cè)到是普通 action 對(duì)象,才交由 reducer 處理。

12.React PureComponent的原理

當(dāng)組件更新時(shí),如果組件的 props 和 state 都沒發(fā)生改變, render 方法就不會(huì)觸發(fā),省去 Virtual DOM 的生成和比對(duì)過(guò)程,達(dá)到提升性能的目的。具體就是 React 自動(dòng)幫我們做了一層淺比較:

if (this._compositeType === CompositeTypes.PureClass) {  shouldUpdate = !shallowEqual(prevProps, nextProps)  || !shallowEqual(inst.state, nextState);}

而 shallowEqual 又做了什么呢?會(huì)比較 Object.keys(state | props) 的長(zhǎng)度是否一致,每一個(gè) key 是否兩者都有,并且是否是一個(gè)引用,也就是只比較了第一層的值,確實(shí)很淺,所以深層的嵌套數(shù)據(jù)是對(duì)比不出來(lái)的。

13.JS調(diào)用原生方法

IOS

RCTBridgeModule 
RCT_EXPORT_MODULE 
RCT_EXPORT_METHOD 
RCT_REMAP_METHOD 
Promises Callbacks

Android

ReactContextBaseJavaModule ReactMethod MyReactPackage里增加模塊

NativeModules.MyNativeModule.callNativeMethod(‘成功調(diào)用原生方法’);

14.原生發(fā)送事件給JS

IOS

RCTEventEmitter sendEventWithName NativeEventEmitter

android

DeviceEventEmitter.addListener

15.immutable.js 的原理

Immutable 實(shí)現(xiàn)的原理是 Persistent Data Structure(持久化數(shù)據(jù)結(jié)構(gòu)),也就是使用舊數(shù)據(jù)創(chuàng)建新數(shù)據(jù)時(shí),要保證舊數(shù)據(jù)同時(shí)可用且不變。同時(shí)為了避免 deepCopy 把所有節(jié)點(diǎn)都復(fù)制一遍帶來(lái)的性能損耗,Immutable 使用了 Structural Sharing(結(jié)構(gòu)共享),即如果對(duì)象樹中一個(gè)節(jié)點(diǎn)發(fā)生變化,只修改這個(gè)節(jié)點(diǎn)和受它影響的父節(jié)點(diǎn),其它節(jié)點(diǎn)則進(jìn)行共享。 Immutable 則提供了簡(jiǎn)潔高效的判斷數(shù)據(jù)是否變化的方法,只需 === 和 is 比較就能知道是否需要執(zhí)行 render(),而這個(gè)操作幾乎 0 成本,所以可以極大提高性能。修改后的 shouldComponentUpdate 是這樣的:

import { is } from 'immutable';shouldComponentUpdate: (nextProps = {}, nextState = {}) => {  const thisProps = this.props || {}, thisState = this.state || {};   if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||      Object.keys(thisState).length !== Object.keys(nextState).length) {    return true;  }   for (const key in nextProps) {    if (!is(thisProps[key], nextProps[key])) {      return true;    }  }   for (const key in nextState) {    if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {      return true;    }  }  return false;}

16.react native redux中間件

react-redux redux-actions redux-promise redux-thunk redux-logger redux-devtools

17.InteractionManager

InteractionManager可以將一些耗時(shí)較長(zhǎng)的工作安排到所有互動(dòng)或動(dòng)畫完成之后再進(jìn)行。這樣可以保證JavaScript動(dòng)畫的流暢運(yùn)行。比如 Navigator的轉(zhuǎn)場(chǎng)動(dòng)畫。

InteractionManager.runAfterInteractions(() => {    navigator.push({        
  component: MainPager,
  name: 'MainPager'   
  })
})
  componentDidMount() {    
    InteractionManager.runAfterInteractions(() => {  
      this.setState({renderPlaceholderOnly: false});  
    });
  }

18.Rect Native 增量更新方案

http://www.itdecent.cn/p/2cb3eb9604ca

19.codePush 接入教程

http://www.itdecent.cn/p/6a5e00d22723

20 React Native 打包參數(shù)

  • --entry-file :JS根目錄文件
  • --platform :選擇平臺(tái)--(ios or android)
  • --transformer :編譯器默認(rèn)編譯器地址(/Users/babytree-mbp13/projects/xcodeProjects/AwesomeProject/node_modules/react-native/packager/transformer.js)
  • --dev :是否是開發(fā)環(huán)境,默認(rèn)為true
  • --prepack :是否需要預(yù)先包裝,默認(rèn)為false
  • --bundle-output :輸出的目錄文件地址
  • --bundle-encoding :編碼格式,默認(rèn)utf8
  • --sourcemap-output :結(jié)果文件存放地址
  • --assets-dest :圖片等資源文件存放地址
  • --verbose :是否開啟日志打印,默認(rèn)為false

Android示例

react-native bundle --entry-file index.android.js --bundle-output ./android/app/src/main/assets/index.android.bundle --platform android --assets-dest ./android/app/src/main/res/ --dev false

iOS 示例

react-native bundle --entry-file index.ios.js --bundle-output ./ios/bundle/index.ios.jsbundle --platform ios --assets-dest ./ios/bundle --dev false
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容