緊接着上一篇文章 React Native 中實現二維碼掃描 當時掃是掃了,東西是出來了,可是並無作界面返回,而自帶的 navigator.pop 方法又沒有參數傳遞,那不是白掃了嗎?javascript
好吧, 這步其實和下面講的沒有什麼關係,不過爲了看下面內容的時候不會混淆,這裏仍是簡單說下。html
React Native 提供了兩個導航組件,NavigatorIOS 和 Navigator。 NavigatorIOS 封裝程度比較高,比較好用,可是隻能在 iOS 上用,Navigator 相對封裝程度比較低,可是爲了之後能方便的給 Android 用,咱們仍是封裝一下 Navigator。java
'use strict';
import React, {Component} from 'react';
import {
View,
Text,
ScrollView,
StyleSheet,
Navigator
} from 'react-native';
export default class Navigation extends Component {
render() {
return (
<Navigator
initialRoute = {{ name:'', component:this.props.component, index:0 }}
configureScene = { ()=>{ return Navigator.SceneConfigs.FloatFromBottom; } }
renderScene = {(route, navigator) => {
const RouteComponent = route.component;
return (
<View style={{ flex:1, paddingTop: 64 }}>
<RouteComponent navigator={navigator} route={route} {...route.passProps} />
</View>
)
}} />
)
}
}複製代碼
這裏使用了 {...route.passProps}
是爲了保持和 NavigatorIOS 同樣的接口,這裏轉場動畫規定了用從下到上彈出的方式,能夠在 configureScene = { ()=>{ return Navigator.SceneConfigs.FloatFromBottom; } }
這裏修改。react
後面的 this.props.navigator
就是從 navigator={navigator}
這裏來的。android
調用的時候還有一點要注意,千萬不要在 Navigator 外面包任何的 View 或者別的什麼,會報錯。ios
index.ios.js中調用:程序員
render() {
return (
<Navigation component={Xxxx} /> ); }複製代碼
利用 passProps
傳一個 callback 函數進去。react-native
調用的地方,book_list.js:微信
_changeText(val) {
this.setState({
keywords:val
})
}
_scan(){
this.props.navigator.push({
component: ScanView,
passProps: {
navigator: this.props.navigator,
callback: this._changeText
}
})
}複製代碼
這裏的 this._changeText
換成一個匿名函數也能夠。函數
返回的地方,scan_view.js:
_show(val) {
this.setState({
code:val.data
})
// Use navigator pop
if( this.props.callback ){
this.props.callback(val.data)
}
if( this.props.navigator ){
this.props.navigator.pop();
}
}複製代碼
經過頁面加回調函數的確能夠解決這個問題,可是若是有多個頁面要用到我掃描的數據,那我除了要在用到掃描數據自己的 View 裏面作邏輯,在掃描這個 View 裏面也要作邏輯,每多一個地方要傳數據,就多一個回調函數。直覺告訴我,這很坑爹。
DeviceEventEmitter 是 React Native 提供的,在 Native 和 JavaScript 之間傳遞消息用的。相似一個發佈訂閱模式,由 DeviceEventEmitter.emit
來發布消息,須要用到的地方使用 DeviceEventEmitter.addListener
來訂閱消息。
調用的地方,book_list.js:
componentDidMount() {
this.subscription = DeviceEventEmitter.addListener('finishScan',this._changeText);
}
componentWillUnmount() {
this.subscription.remove();
}複製代碼
注意,這裏咱們訂閱消息是在組件 mount 以後,同時咱們須要在合適的時候手動取消訂閱 this.subscription.remove();
不然可能會致使內存泄露。
返回的地方,scan_view.js:
_show(val) {
this.setState({
code:val.data
})
// Use DeviceEventEmitter
DeviceEventEmitter.emit('finishScan',val.data);
if( this.props.navigator ){
this.props.navigator.pop();
}
}複製代碼
這裏就是當咱們掃描到東西,就觸發一個叫 finisScan
的事件,並退出當前 View,在 book_list.js 中就能夠收到這個事件,並作相應處理。若是有別的地方須要用到掃描的數據,直接訂閱這個事件就能夠了,在 scan_view.js 中不須要額外的處理。
在調試過程當中,還遇到一個問題 A valid provisioning profile for this executable was not found
大意就是證書沒了,打開個人調試設備 iPad,通用-描述文件與設備管理 果真上週作掃描的時候用的證書沒了,Xcode 打開項目,找到簽名證書那裏,原來這種測試證書是有期限的,一個星期,恰好剛纔過時了。從新點一下又能夠得到七天的 buff 了。
有時候當你意識到用了一種很差的方法實現了某個功能的時候,你須要去尋找尋找是否有更優雅的方法,畢竟人生已經如此的艱難,不要爲本身挖坑。
最近總想記錄一些所思所想,寫寫科技與人文,寫寫生活狀態,寫寫讀書感悟,主要是扯淡和感悟,歡迎關注,交流。
微信公衆號:程序員的詩和遠方
公衆號ID : MonkeyCoder-Life