React Native:页面跳转传值

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/new_Aiden/article/details/72566640

在app开发中,跳转页面的需求是最常见的。
Android原生跳转可以使用startActivityForResult、startActivity实现…
但是在React Native中呢?
作为得到前端青睐的React Native,使用Navigator结合路由的方式进行跳转。路由其实很好理解,就是一个url映射到具体的函数。
比如说:

# flask框架
@app.route("/login")
def login():
    # 只要是/login的网址,就会跳进这个函数

// Spring
@RequestMapping("/login")
public void login() {
    // 只要是/login的网址,就会跳进这个函数
}

例子太多太多了。。。其实,Android开发框架——Router、LiteRouter等等都是以路由的方式实现原生Android界面跳转。

扯远了,这里开始真正的学习React Native界面跳转。这里需要了解一个Navigator这个api了。
需要说明的是,我们需要先定义一个没有任何界面的Component,并在这个Component初始化Navigator。

// SplashComponent.js
class SplashComponent extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        // 这里定义第一个界面的name和对应的Component
        const defaultName = "LoginComponent";
        const defaultComponent = LoginComponent;

        return (
            <Navigator
                // 初始化路由
                initialRoute={{name: defaultName, component: defaultComponent}}
                // 配置界面跳转的动画效果
                configureScene={
                    (route) => {
                        return Navigator.SceneConfigs.FloatFromBottom;
                    }
                }
                // 跳转后,渲染界面的函数
                renderScene={
                    (route, navigator) => {
                        let Component = route.component;
                        return <Component{...route.params} navigator={navigator}/>
                    }
                }
            />
        );
    }
}

我们将定义的SplashComponent作为第一个界面。实际上,SplashComponent并没有开始任何的View显示,只是将界面跳转到了LoginComponent。

别忘了这句话

AppRegistry.registerComponent('Animation', () => SplashComponent);

接下来就是LoginComponent的编写了,这里就是一个简单的Text,点击Text后,会跳转到RegisterComponent。

// LoginComponent.js
class LoginComponent extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <View>
                <Text onPress={this.onPress.bind(this)}>点击后跳转到Register</Text>
            </View>
        )
    }

    onPress() {
        const {navigator} = this.props;
        navigator.push({
            name: "RegisterComponent",
            component: RegisterComponent,
            // 传递参数,因为前面初始化Navigator的时候是使用了params,所以这里就用params
            params : {
                string : "login",
            }
        });
    }
}
class RegisterComponent extends Component {

    constructor(props) {
        super(props);
        // 这样获取参数
        console.log(props.string);
    }

    render() {
        return (
            <Text onPress={() => {
                const {navigator} = this.props;
                // 将该界面弹出栈
                navigator.pop();
            }}>注册</Text>
        )
    }
}

上面演示了如何在两个界面中传递参数。navigator有两个重要的方法——push、pop。也就是说,本质上React Native有一个保存Scene的栈,通过管理这个栈实现界面的跳转。
但是,我们按下返回键的时候,其实并不会调用Navigator.pop()。个人推测React Native的实现会将所有的Scene都显示在一个Activity上,并不存在Activity的交互,按下返回键才不会弹出Scene。

那我们可以通过监听返回键的方式,实现弹出Scene。参数资料:https://reactnative.cn/docs/0.43/backandroid.html#content

但是,我们通过navigtor.push是相当于实现了startActivity。还没有实现startActivityForResult。
我们可以通过以下方法实现:

    changeData(data) {
        this.setState({
            data : data
        });
    }

    // LoginComponent.js
    // 省略部分代码
    onPress() {
        const {navigator} = this.props;
        navigator.push({
            name: "RegisterComponent",
            component: RegisterComponent,
            params : {
                string : "login",
                // 将回调函数通过参数的形式传递过去
                changeData : changeData
            }
        });
    }
    // RegisterComponent.js
    // 省略部分代码
    const {navigator} = this.props;
    // 在这里调用那个函数
    this.props.changeData("回调");
    navigator.pop();

上述方式通过函数回调的方式解决了Navigator.pop无法传值得问题。这种方法基本解决了很多问题,但是总感觉写一个回调函数是很不妥的方式。

我们还可以通过React Native提供的DeviceEventEmitter的api实现传值。其实DeviceEventEmitter的本质实现是发布者与监听者模式。

// LoginComponent.js
// 省略部分代码
componentDidMount() {
    //这里监听的事件是changeData,监听到后会自动回调changeData函数
    DeviceEventEmitter.addListener('changeData', this.changData);
}

// 这里一定要移除事件的监听,避免内存泄漏
componentWillUnmount() {
    this.subscription.remove();
}
// RegisterComponent.js
// 省略部分代码
// 发布事件
DeviceEventEmitter.emit('changeData',val.data);
navigator.pop();

猜你喜欢

转载自blog.csdn.net/new_Aiden/article/details/72566640