React Native学习之Navigator组件

Navigator组件初探

一个应用往往是由多功能视图组成!多页面的切换:路由或导航

在RN中专门负责视图切换的组件:NavigatorNavigatorIOS

导航器对比:

NavigatorNavigatorIOS都可以用来管理应用中“场景”的导航(也可以称作屏幕)。导航器建立了一个路由栈,用来弹出,推入或者替换路由状态。它们和html5中的history API很类似。主要的区别在于NavigatorIOS使用了iOS中的UINavigationController类,而Navigator则完全用js重写了一个类似功能的React组件。因此Navigator可以兼容iOS和Android,而NavigatorIOS只能用于iOS。

NavigatorIOS:轻量、受限的API设置,使其相对Navigator来说不太方便定制。由开源社区主导开发 —— React Native的官方团队并不在自己的应用中使用。对于大多数正式的App开发,我们建议使用Navigator —— 使用NavigatorIOS实现复杂的需求很容易碰到麻烦。

原理

导航器通过路由对象来分辨不同的场景。利用renderScene方法,导航栏可以根据指定的路由来渲染场景。

可以通过configureScene属性获取指定路由对象的配置信息,从而改变场景的动画或者手势。

class RNAPP extends Component {
    render() {
        let defaultName='List';
        let defaultComponent=List;
        return (
            <Navigator
                initialRoute={{ name: defaultName, component: defaultComponent }}
                //配置场景
                configureScene = {
                    (route) => {
                    //这个是页面之间跳转时候的动画,具体有哪些?可以看这个目录下,有源代码的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
                        return Navigator.SceneConfigs.VerticalDownSwipeJump;
                    }
                }

                renderScene = {
                    (route, navigator) => {
                        let Component = route.component;
                        return <Component {...route.params} navigator={navigator} />
                    }
                }
            />
        );
    }
}

可以看到回调里的两个参数:route, navigator

通过打印我们发现route里其实就是我们传递的name,component这两个对象,navigator是一个Navigator的对象,它有push pop jump...等方法,这是我们用来跳转页面用的那个navigator对象。

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    _pressButton() {
        const { navigator } = this.props;
        //为什么这里可以取得 props.navigator?请看上文:
        //<Component {...route.params} navigator={navigator} />
        //这里传递了navigator作为props
        if(navigator) {
            navigator.push({
                name: 'Detail',
                component: Detail,
            })
        }
    }

    render(){
        return (
            <ScrollView style={styles.flex}>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >☆ 豪华邮轮济州岛3日游</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮台湾3日游</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮地中海8日游</Text>
            </ScrollView>
        );
    }
}

这里有一个判断,也就是如果传递进来的component存在,那我们就是返回这个component,结合前面 initialRoute 的参数,我们就是知道,这是一个会被render出来给用户看到的component,然后navigator作为props传递给了这个component。

所以下一步,我们可以直接拿到这个props.navigator

源码

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

import React, {
    AppRegistry,
    Component,
    StyleSheet,
    PixelRatio,
    Navigator,
    ScrollView,
    Text,
    View
} from 'react-native';

class RNAPP extends Component {
    render() {
        let defaultName='List';
        let defaultComponent=List;
        return (
            <Navigator
                initialRoute={{ name: defaultName, component: defaultComponent }}
                //配置场景
                configureScene = {
                    (route) => {
                    //页面之间跳转的动画,具体值可以查看源代码: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
                        return Navigator.SceneConfigs.VerticalDownSwipeJump;
                    }
                }

                renderScene = {
                    (route, navigator) => {
                        let Component = route.component;
                        return <Component {...route.params} navigator={navigator} />
                    }
                }
            />
        );
    }
}

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    _pressButton() {
        const { navigator } = this.props;
        //为什么这里可以取得 props.navigator?请看上文:
        //<Component {...route.params} navigator={navigator} />
        //这里传递了navigator作为props
        if(navigator) {
            navigator.push({
                name: 'Detail',
                component: Detail,
            })
        }
    }

    render(){
        return (
            <ScrollView style={styles.flex}>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >☆ 豪华邮轮济州岛3日游</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮台湾3日游</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮地中海8日游</Text>
            </ScrollView>
        );
    }
}

class Detail extends Component{
    constructor(props) {
        super(props);
        this.state = {};
    }

    _pressButton() {
        const { navigator } = this.props;
        if(navigator) {
            //很熟悉吧,入栈出栈~ 把当前的页面pop掉,即可返回上一个页面
            navigator.pop();
        }
    }

    render(){
        return(
            <ScrollView>
              <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >点击我可以跳回去</Text>
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    flex:{
        flex:1,
    },
    list_item:{
        height:40,
        marginLeft:10,
        marginRight:10,
        fontSize:20,
        borderBottomWidth:1,
        borderBottomColor:'#ddd',
        justifyContent:'center',
    },
});

AppRegistry.registerComponent('RNAPP', () => RNAPP);

Navigator参数传递

怎么传递参数过去,或者从对方获取参数。

从列表页跳转至详情页

(1)传递参数,通过push方法。

navigator.push({
    name: 'Detail',
    component: Detail,
    params:{
        author: this.state.author,
    }
})

这个语法是把routes.params里的每个 key 作为 props 的一个属性:{...route.params}

(2)提取参数

componentDidMount() {
    this.setState({
        author:this.props.author,
    });
}

(3)使用参数

{this.state.author}

源码:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

import React, {
    AppRegistry,
    Component,
    StyleSheet,
    PixelRatio,
    Navigator,
    ScrollView,
    Text,
    View
} from 'react-native';

class RNAPP extends Component {
    render() {
        let defaultName = 'List';
        let defaultComponent = List;
        return (
            <Navigator
                initialRoute = {{ name: defaultName, component: defaultComponent }}
                //配置场景
                configureScene = {
                    (route) => {
                        //这个是页面之间跳转时候的动画,具体有哪些?可以看这个目录下,有源代码的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
                        return Navigator.SceneConfigs.VerticalDownSwipeJump;
                    }
                }
                renderScene = {
                    (route, navigator) => {
                        let Component = route.component;
                        return <Component {...route.params} navigator={navigator} />
                    }
                }
            />
        );
    }
}

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {
            author:'rnapp.cc'
        };
    }

    _pressButton() {
        const { navigator } = this.props;
        //为什么这里可以取得 props.navigator?请看上文:
        //<Component {...route.params} navigator={navigator} />
        //这里传递了navigator作为props
        if (navigator) {
            navigator.push({
                name: 'Detail',
                component: Detail,
                params:{
                    author: this.state.author,
                }
            })
        }
    }

    render(){
        return (
            <ScrollView style={styles.flex}>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >☆ 豪华邮轮济州岛3日游</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮台湾3日游</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮地中海8日游</Text>
            </ScrollView>
        );
    }
}

class Detail extends Component{
    constructor(props) {
        super(props);
        this.state = {};
    }

    componentDidMount() {
        this.setState({
            author:this.props.author,
        });
    }

    _pressButton() {
        const { navigator } = this.props;
        if(navigator) {
            //很熟悉吧,入栈出栈~ 把当前的页面pop掉,即可返回上一个页面
            navigator.pop();
        }
    }

    render() {
        return(
            <ScrollView>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >作者是:{this.state.author}</Text>
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    flex:{
        flex:1,
    },
    list_item:{
        height:40,
        marginLeft:10,
        marginRight:10,
        fontSize:20,
        borderBottomWidth:1,
        borderBottomColor:'#ddd',
        justifyContent:'center',
    },
});

AppRegistry.registerComponent('RNAPP', () => RNAPP);

从详情页返回至列表页

综合实例:从列表页传递用户id给详情页,详情页跟进用户id查询用户信息,并把
用户信息回传给列表页显示出来

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

import React, {
    AppRegistry,
    Component,
    StyleSheet,
    PixelRatio,
    Navigator,
    ScrollView,
    Text,
    View
} from 'react-native';

class RNAPP extends Component {
    render() {
        let defaultName='List';
        let defaultComponent=List;
        return (
            <Navigator
                initialRoute = {{ name: defaultName, component: defaultComponent }}
            //配置场景
                configureScene = {
                    (route) => {
                        //这个是页面之间跳转时候的动画,具体有哪些?可以看这个目录下,有源代码的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
                        return Navigator.SceneConfigs.VerticalUpSwipeJump;
                    }
                }
                renderScene = {
                    (route, navigator) => {
                        let Component = route.component;
                        return <Component {...route.params} navigator={navigator} />
                   }
                }
            />
        );
    }
}

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {
            id:1,
            user:null,
        };
    }

    _pressButton() {
        const { navigator } = this.props;
        //为什么这里可以取得 props.navigator?请看上文:
        //<Component {...route.params} navigator={navigator} />
        //这里传递了navigator作为props
        const self = this;
        if (navigator) {
            navigator.push({
                name: 'Detail',
                component: Detail,
                params:{
                    id: this.state.id,
                    //从详情页获取user
                    getUser: function(user) {
                        self.setState({
                            user: user
                        })
                    },
                }
            })
        }
    }

    render() {
        if (this.state.user) {
            return(
                <View>
                    <Text style={styles.list_item}>用户信息: { JSON.stringify(this.state.user) }</Text>
                </View>
            );
        } else {
            return (
                <ScrollView style={styles.flex}>
                    <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >☆ 豪华邮轮济州岛3日游</Text>
                    <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮台湾3日游</Text>
                    <Text style={styles.list_item} onPress={this._pressButton.bind(this)}>☆ 豪华邮轮地中海8日游</Text>
                </ScrollView>
            );
        }
    }
}

const USER_MODELS = {
    1: { name: '张三', age: 23 },
    2: { name: '李四', age: 25 }
};

class Detail extends Component {
    constructor(props) {
        super(props);
        this.state = {
            id: null
        };
    }

    componentDidMount() {
        //这里获取从FirstPageComponent传递过来的参数: id
        this.setState({
            id: this.props.id
        });
    }

    _pressButton() {
        const { navigator } = this.props;
        if (this.props.getUser) {
            let user = USER_MODELS[this.props.id];
            this.props.getUser(user);
        }

        if (navigator) {
            //很熟悉吧,入栈出栈~ 把当前的页面pop掉,即可返回上一个页面
            navigator.pop();
        }
    }

    render() {
        return(
            <ScrollView>
                <Text style={styles.list_item} >传递过来的用户id是:{this.state.id}</Text>
                <Text style={styles.list_item} onPress={this._pressButton.bind(this)} >点击我可以跳回去</Text>
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    flex:{
        flex:1,
    },
    list_item:{
        height:40,
        marginLeft:10,
        marginRight:10,
        fontSize:20,
        borderBottomWidth:1,
        borderBottomColor:'#ddd',
        justifyContent:'center',
    },
});

AppRegistry.registerComponent('RNAPP', () => RNAPP);

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-learning-navigator-component/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
React Native学习之Navigator组件
Navigator组件初探 一个应用往往是由多功能视图组成!多页面的切换:路由或导航 在RN中专门负责视图切换的组件:Navigator、NavigatorIOS 导航器对比: Navig……
<<上一篇
下一篇>>
文章目录
关闭
目 录