恍惚間3個月過去了,做爲揭棺而起的失蹤人口,遲來的第三篇,也是react native原生相關的最後的一篇,是時候給收個尾了。此次就不廢話了,直接上主題( ̄^ ̄)ゞ。javascript
react native的高效,在於其中大部分組件,都是基於原生封裝的,js中對組件的配置與操做,最終都會轉化爲native控件行爲。以上的這段廢話,總結起來就是:react native經過統一的接口封裝,把原生控件轉爲js組件使用。java
既然有官方封裝,那確定少不了自定義控件。react native自定義組件仍是很方便的,關鍵就在於ViewManager/ViewGroupManager。從類名上,很明顯是對應原生中的View和ViewGroup。node
(PS :react native 中的View組件,封裝的實際上是ViewGroupManager,因此View組件才能夠包裹子組件,組件中的ZIndex屬性,其實就是子組件在add到ViewGroup中前後,以下圖) react
其餘的內部細節就不深究咯,愉悅的奔向主題吧(˶‾᷄ ⁻̫ ‾᷅˵)。注意,下方代碼分析大部分來自如下路徑:git
//js組件
node_modules/react-native/Libraries/Components/View
node_modules/react-native/Libraries/Components/WebView
//原生java
react-native-0.xx.x/com.facebook/react/views/view
react-native-0.xx.x/com.facebook/react/views/webview複製代碼
首先咱們須要實現一個XXXGroupManager,繼承於ViewGroupManager。其中最主要的即是重載實現getName和creatViewInstance兩個方法。github
getName
指定了XXXGroupManager在js組件中獲取的名稱。web
creatViewInstance
建立了自定義控件在Manager中使用,這裏只要將你在原生端的自定義控件,生成便可。react-native
js組件中,使用requireNativeComponent
,能夠經過上面中getName指定的名稱,獲取到對應的控件,以下圖,經過獲取到的控件,就能夠配置對應的接口啦ε-(´∀`; )。ui
關於requireNativeComponent的使用說明參考下圖 this
react native 提供 @ReactProp
和 @ReactPropGroup
註解,爲js組件提供接口,配置原生控件的屬性。以下圖1,name = "borderStyle" 表示,js組件能夠經過borderStyle設置控件的borderStyle,如圖2。若是須要默認值,能夠增長default屬性。
這裏須要注意,@ReactPropGroup是一組相近的屬性設置註解,如設置UI的上下左右的不一樣寬度,原生中經過index判斷,而它們在js端組件的設置,能夠統一到原生中的一個接口。
react native提供原生控件對js組件的交互支持,和上一篇文章相似,也是經過事件機制發送,發送消息到js組件中,js組件經過監聽事件的callback處理消息。
首先,在 UIManagerModuleConstants.java
中,如圖4,react native默認映射了一些組件的消息事件名,如topChange在js組件中經過onChange監聽,這樣在原始中經過topChange發送的消息,就能夠在組件中的onChange接收到消息。
消息中的參數,能夠經過WritableMap傳遞數據,利用rctEventEmitter發送消息。
有時候,你可能還須要自定義本身的消息名,那麼你須要重寫getExportedCustomDirectEventTypeConstants
,只有註冊了你的映射消息關係,才能夠在js組件中,正常接收到你自定的消息名的消息。
既然原生控件能夠操做組件,那麼js組件也有控制原生控件的需求。這時候咱們能夠重載 getCommandsMap
,用來註冊js組件支持的操做行爲,經過 receiveCommand
處理操做,如在js組件中調用reload,就會觸發原生XXXGroupManager中receiveCommand的root.reload,從而與原生控件交互。
圖9中,經過UIManager,發送命令到原生。
這類使用方式,相似的使用場景有,例如
//textInput組件中主動獲取焦點
UIManager.dispatchViewManagerCommand(
ReactNative.findNodeHandle(this.textInput),
UIManager.AndroidTextInput.Commands.focusTextInput,
null);複製代碼
最終在原生端配置結束後,js端配置完對應邏輯,經過 module.exports = WebView
導出組件使用。
拖了這麼久,react native和andorid原生相關的文章終於收尾啦(◐‿◑),也算是對react native的一個里程碑吧。在實際開發中,react native的代碼的複用率仍是挺高的,做爲跨平臺開發的一種,仍是蠻推薦你們嘗試下。
接下來有時間會把github的demo完善下,畢竟demo落下的有點多了,歡迎你們關注喲ε-(´∀`; )。
我的github入口:github.com/CarGuo