React Native 解决 Navigator.pop 没法传参数

紧接着上一篇文章 React Native 中实现二维码扫描 当时扫是扫了,东西是出来了,可是并无作界面返回,而自带的 navigator.pop 方法又没有参数传递,那不是白扫了吗?javascript

封装 Navigator

好吧, 这步其实和下面讲的没有什么关系,不过为了看下面内容的时候不会混淆,这里仍是简单说下。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

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

参考

reactnative.cn/docs/0.36/n…

www.jianshu.com/p/f7d569407…

bbs.reactnative.cn/topic/20/%E…

相关文章
相关标签/搜索