1. 程式人生 > >[深入剖析React Native]React Native元件之Navigator

[深入剖析React Native]React Native元件之Navigator

1.簡介

導航元件Navigator可以讓app在不同頁面進行切換。為達到這樣的功能,Navigator提供了路由物件功能進行區分每個頁面。
我們可以通過renderScene方法,Navaigator根據指定的路由進行渲染指定的介面。
除了以上功能之外,為了改變頁面切換的動畫或者頁面的手勢,該元件還提供configureScene屬性來進行獲取指定路由頁面的配置物件資訊。
對於頁面切換動畫或者更多的螢幕配置選項資訊詳情可以檢視Navigator.SceneConfigs

2.動畫手勢屬性

PushFromRight
FloatFromRight
FloatFromLeft
FloatFromBottom
FloatFromBottomAndroid
FadeAndroid
HorizontalSwipeJump
HorizontalSwipeJumpFromRight
VertivalUpSwipeJump
VertivalDownSwipeJump
更多屬性,可以去修改NavigatorSceneConfigs.js這個檔案。

3.Navigator方法

在使用導航器的時候,如果你已經獲取了導航器物件的引用,我們可以進行呼叫以下一些方法來實現頁面導航功能:getCurrentRoutes() 該進行返回存在的路由列表資訊
getCurrentRoutes() 返回存在的路由列表資訊
jumpBack() 回退操作,但是不會解除安裝(刪除)當前頁面
jumpForward() 跳轉到相對於當前頁面的下一個頁面
jumpTo(route) 根據傳入的路由資訊,跳轉到一個指定的頁面(該頁面不會解除安裝刪除)
push(route) 導航切換到一個新的頁面,新的頁面進行壓入棧。通過jumpForward()方法可以回退過去
pop 當前頁面彈出來,跳轉到棧中下一個頁面,並且解除安裝刪除掉當前的頁面
replace(route) 只用傳入的路由的指定頁面進行替換掉當前的頁面
replaceAtIndex(route, index) 傳入路由以及位置索引,使用該路由指定的頁面跳轉到指定位置的頁面
replacePrevious(route) 傳入路由,通過指定路由的頁面替換掉前一個頁面
resetTo(route) 進行導航到新的介面,並且重置整個路由棧
immediatelyResetRouteStack(routeStack) 該通過一個路由頁面陣列來進行重置路由棧
popToRoute(route) 進行彈出相關頁面,跳轉到指定路由的頁面,彈出來的頁面會被解除安裝刪除
popToTop() 進行彈出頁面,導航到棧中的第一個頁面,彈出來的所有頁面會被解除安裝刪除

4.Navigator屬性風格

configureScene -- function 方法, 該為可選的方法進行配置頁面切換動畫和手勢。該會通過路由和路由棧兩個引數呼叫,進行返回一個頁面引數配置物件:(route, routeStack) => Navigator.SceneConfigs.FloatFromRight
initialRoute -- object 引數物件, 進行設定導航初始化的路由頁面。路由是標識導航器渲染標識每一個頁面的物件。initialRoute必須為initialRouteStack中的路由。同時initialRoute預設為initialRouteStack中路由棧的最後一項
initialRouteStack -- [object] 引數物件陣列 該是一個初始化的路由陣列進行初始化。如果initalRoute屬性沒有設定的話,那麼就必須設定initialRouteStack屬性,使用該最後一項作為初始路由。 如果initalRouteStack屬性沒有設定的話,該會生成只包含initalRoute值的陣列
navigationBar -- node 該為可選的引數,在頁面切換中用來提供一個導航欄
navigator -- object 該為可選引數,可以從父類導航器中獲取導航器物件
onDidFoucs -- function 該方法已經廢棄,我們可以使用navigationContext.addListener(‘didfocus’,callback)方法進行替代。該會在每次頁面切換完成或者初始化之後進行呼叫該方法。該引數為新頁面的路由
onWillFocus --function 該方法已經廢棄,我們可以使用navigationContext.addListener(‘willfocus’,callback)方法進行替代。該會頁面每次進行切換之前呼叫
renderScene -- function 該為必須呼叫的方法,該用來渲染每一個路由指定的頁面。引數為路由以及導航器物件兩個引數,具體是方法如下:

(route, navigator) =><MySceneComponent title={route.title} navigator={navigator} />

sceneStyle -- 樣式風格,該繼承了View檢視的所有樣式風格。該設定用於每個頁面容器的風格

5.例項

'use strict';

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

class NavButton extends Component {
    render() {
        return (
            <TouchableHighlight
                style={styles.button}
                underlayColor="#B5B5B5"
                onPress={this.props.onPress}>
                <Text style={styles.buttonText}>{this.props.text}</Text>
            </TouchableHighlight>
        );
    }
}

class HomeScene extends Component {
    render() {
        return(
            <View style={styles.container}>
                <NavButton 
                    onPress={() => {
                        this.props.navigator.push({
                            component: ConfigsScene,
                            name: '手勢屬性',
                        });
                    }}
                    text='手勢屬性'
                />
                <NavButton 
                    onPress={() => {
                        this.props.navigator.push({
                            component: MethodsScene,
                            name: '方法',
                        });
                    }}
                    text='方法'
                />
            </View>
        );
    }
}

class ConfigsScene extends Component {
    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.messageText}>{this.props.message}</Text>
                <NavButton
                    onPress={() => {
                        this.props.navigator.pop();
                    }}
                    text="返回上一頁"
                />

                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.PushFromRight,
                        });
                    }}
                    text="PushFromRight default"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.FloatFromRight,
                        });
                    }}
                    text="FloatFromRight"
                    />
                    <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.FloatFromLeft,
                        });
                    }}
                    text="FloatFromLeft"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.FloatFromBottom,
                        });
                    }}
                    text="FloatFromBottom"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.FloatFromBottomAndroid,
                        });
                    }}
                    text="FloatFromBottomAndroid"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.FadeAndroid,
                        });
                    }}
                    text="FadeAndroid"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.HorizontalSwipeJump,
                        });
                    }}
                    text="HorizontalSwipeJump"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.HorizontalSwipeJumpFromRight,
                        });
                    }}
                    text="HorizontalSwipeJumpFromRight"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.VerticalUpSwipeJump,
                        });
                    }}
                    text="VerticalUpSwipeJump"
                    />
                <NavButton
                    onPress={() => {
                        this.props.navigator.push({
                            component: EndScene,
                            sceneConfig: Navigator.SceneConfigs.VerticalDownSwipeJump,
                        });
                    }}
                    text="VerticalDownSwipeJump"
                    />
            </View>
        );
    }
}

class MethodsScene extends Component {
    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.messageText}>Current Routes length: {this.props.navigator.getCurrentRoutes().length}</Text>
                <NavButton 
                    onPress={() => {
                        this.props.navigator.jumpBack();
                    }}
                    text='jumpBack'
                />
                <NavButton 
                    onPress={() => {
                    }}
                    text='jumpForward'
                />
                <NavButton 
                    onPress={() => {
                    }}
                    text='jumpTo'
                />
            </View>
        );
    }
}


class EndScene extends Component {
    render() {
        return (
            <View style={styles.container}>
                <NavButton
                    onPress={() => {
                        this.props.navigator.pop();
                    }}
                    text="返回上一頁"
                />
                <NavButton
                    onPress={() => {
                        this.props.navigator.popToTop();
                    }}
                    text="退到棧中第一個頁面"
                />
            </View>
        );
    }
}

export default class NavigatorMazouri extends Component {
    render() {
        return (
            <Navigator 
                style={styles.container}
                initialRoute={{
                    component: HomeScene,
                    name: 'home'
                }}
                renderScene={(route, navigator) => {
                    let Component = route.component;
                    if(route.component) {
                    return <Component {...route.params} navigator={navigator} />
                    }
                }}
                configureScene={(route) => {
                    if (route.sceneConfig) {
                        return route.sceneConfig;
                    }
                    return Navigator.SceneConfigs.PushFromRight;
                }}
            />
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        backgroundColor: '#F5FCFF',
    },
    messageText: {
        fontSize: 17,
        fontWeight: '500',
        padding: 15,
        marginTop: 50,
        marginLeft: 15,
    },
    button: {
        backgroundColor: 'white',
        padding: 15,
        borderBottomWidth: StyleSheet.hairlineWidth,
        borderBottomColor: '#CDCDCD',
    },
});