react native 強大的navigation V2.0+

前言

筆者在V2版之前使用的版本是 1.5.1,現項目中升級到2.6.2。以下是我使用這兩個版本的一些經驗,分享給大家,希望節省大家一些寶貴的時間。

注意/優化項

導航器導出名字改變

升級前:

import { StackNavigator, TabNavigator, DrawerNavigator} from 'react-navigation'

升級後:

import {  createStackNavigator, createBottomTabNavigator, createDrawerNavigator } from 'react-navigation'

新增getParam('id', '默認值');

通過navigate傳餐到下一個界面可以設置默認值了,再也不用在接受的界面使用三元表達式判斷傳入值是否存在了。

let {navigation} = this.props;
        this.state = {
            id: navigation.getParam('id', 0) //如果沒有接收到id,給id賦值爲0
        }

正文

我在使用 1.5.1版的時候遇到過下面這樣的需求:

需求一:界面跳轉:需要實現 A——>B B——>C C——>A,甚至更深層次的界面跳轉到A

需求二:需要使用多個導航器,而且相互之間不影響。(引導頁,登陸,註冊,忘記密碼的等界面的實現)。

需求三:一個界面多次被使用,(比如一個社交的帖子詳情,點擊頭像進入個人主頁,在個人主頁中點擊帖子,又進入到帖子詳情,然後再點擊帖子中的頭像進入到個人主頁。這樣帖子詳情 個人主頁兩個界面會被無限循環調用)。

需求四:快速點擊時跳轉下個界面,不要跳轉多個相同的界面(這應該算V1+的一個缺陷)。

接下來我就根據上面的幾個需求來分析在 V1.0+V2.0+ 分別是如何實現的。

需求一 V1.0+
我的實現思路是:
使用DeviceEventEmitter在B界面註冊了一個返回上一個界面的goback事件, 事件觸發時執行this.props.naviagtion.goBack();,然後在C界面先調用DeviceEventEmitter.emit('B界面註冊的事件名'),然後再調用 this.props.naviagtion.goBack()就能達到 C——>A的效果。雖然實現了,但是心裏暗地裏說了一句mmp。

需求一V2.0+

直接在C界面調用this.props.naviagtion.navigate('A')就可以實現 C——>A的效果,如果A是首頁的話可以調用this.props.naviagtion.popToTop()

需求二V1.0+

登陸註冊界面:使用的是Modal組件,自定義的全屏懸浮窗。

需求二V2.0+

V2.0中提供了一個createSwitchNavigator,這個組件的作用個人的理解是導航器分離,永遠只展示一個導航器,你可以設置多個導航器,並且當多個導航器相互切換的時候都會銷燬掉其他導航器。(如何嵌套實現請看最後面的代碼)

需求三V1.0+
正常使用this.props.navigation.navigate('A')可以實現這種效果(但是點擊太快會多次導航到同一個界面)。

需求三V2.0+
需要注意的是V2.0+實現這種效果需要調用 this.props.navigation.push('A'),如果調用了this.props.navigation.navigate('A')你會發現當A已經在導航棧中界面跳轉效果是返回到這個界面的效果;如果A是當前界面,再次調用navigate('A')沒有任何效果,但是push('A')還可以繼續導航到A界面。

需求四V1.0+

解決方案:在你配置導航器的.js文件最下面 export default xxx之前粘貼下面的代碼

 /**解決點擊太快跳轉連續跳轉多個界面**/

    //主要是這一步
    const navigateOnce = (getStateForAction) => (action, state) => {
        const {type, routeName} = action;
        return (
            state &&
            type === NavigationActions.NAVIGATE &&
            routeName === state.routes[state.routes.length - 1].routeName
        ) ? null : getStateForAction(action, state);
    };

    //這是第二步
    MainStackNavigator.router.getStateForAction = navigateOnce(MainStackNavigator.router.getStateForAction);

需求四V2.0+
只需要正常調用this.props.navigation.navigate('A')就可以了,官方已經修復了這個bug。

各種導航器嵌套代碼


import {
    createStackNavigator,
    createBottomTabNavigator,
    createDrawerNavigator,
    createSwitchNavigator,
} from 'react-navigation'


const navigationOptions = {
    headerStyle:{
        backgroundColor: '#fff'
    },
    headerTintColor: '#666666',
    headerBackTitle: null,
    headerTitleStyle: {
        fontWeight: 'bold',
    },
    drawerLockMode:'locked-closed' 
};

        //首頁導航器
const HomeStack = createStackNavigator(
    {
        Home: HomeScreen,
        HomeDetail: HomeDetailScreen,
        //其他首頁導航棧下的界面
      
    },
    {
        navigationOptions:navigationOptions
    });

        //新聞導航器
const NewsStack = createStackNavigator({
        News: NewsScreen,
        NewsDetail: NewsDetailScreen,
         //其他新聞導航棧下的界面
    },
    {
        navigationOptions:navigationOptions
    });

    //登陸、註冊等導航器
const LoginStack = createStackNavigator(
    {
        Login: LoginScreen,
        Register: RegisterScreen,
        Bind: BindScreen,
        UserProtocol: UserProtocolScreen
      //其他登陸導航棧下的界面
    },
    {
        navigationOptions:navigationOptions
    });


    //tab點擊切換導航器
const Tab = createBottomTabNavigator({
    Home: HomeStack,
    News: NewsStack
},{
    initialRouteName: 'Home',
    tabBarOptions: {
        showLabel: false,
        style:{
            height:0 //隱藏底部切換
        }
    }
});

    //側滑導航器
const drawerNavigator = createDrawerNavigator({
    bottomTab: Tab,
},{
    drawerWidth: width-120,
    contentComponent: CustomDrawerContentComponent
});


    //最後導出Switch導航器
export default createSwitchNavigator({
    drawerNavigator: drawerNavigator,
    loginStack: LoginStack,

})

歡迎 ❤️ 關注 你們的認可是我寫作最大的動力,如果有什麼錯誤的地方或者疑問歡迎在評論區留言討論,我看到後會儘快回覆大家。😊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章