如果用户已登录,则更改路由名称和组件

Posted

技术标签:

【中文标题】如果用户已登录,则更改路由名称和组件【英文标题】:Change route name and component if user is logged in 【发布时间】:2019-11-19 07:12:56 【问题描述】:

我的 nativescript-vue 中有一个使用 RadSideDrawer 的登录组件。

我想做的就是将Login 路由更改为Logout,但我似乎不知道如何实现这一点。三元运算符不会完全起作用。

我还尝试声明一个新的空数组并将我的菜单数组放入其中并操作它而不是原始数据。这也不起作用。

我需要关闭应用程序并再次打开它才能更改菜单​​项,它不是反应式的。

首先,这里是我的app.js

Vue.prototype.$routes = routes

new Vue(
    store,
    render (h) 
        return h(
          App,
          [
            h(DrawerContent,  slot: 'drawerContent' ),
            //h(store.getters.loggedIn ? routes.Home : routes.Login,  slot: 'mainContent' )
            h(routes.Home,  slot: 'mainContent' )
          ]
        )
      
  ).$start()

这是我在router/index.js 中的路由器,我在这里声明了路由器。

import Home from "../components/Home";
import Browse from "../components/Browse";
import Featured from "../components/Featured";
import Search from "../components/Search";
import Settings from "../components/Settings";
import Tasks from "../components/Tasks";
import Login from "../components/Login";
import Logout from "../components/Logout";

const routes = 
    Home,
    Browse,
    Featured,
    Search,
    Settings,
    Tasks,
    Login,
    Logout


export default routes

我还使用$store 和一堆getter、setter、突变和动作,如果用户登录,其中一个getter 检索

export const store = new Vuex.Store(
    state: 
        token: LS.getItem('access_token') || null,
        filter: 'all',
        todos: [],
        msg: ''
    ,
    getters: 
        loggedIn(state) 
            return state.token !== null
        ,
    

由于我使用的是抽屉导航,这里是DrawerContent.vue

<template lang="html">
    <GridLayout rows="auto, *" class="sidedrawer sidedrawer-left">
        <StackLayout row="0" class="sidedrawer-header">
            <Label class="sidedrawer-header-image fa" text.decode="&#xf2bd;"></Label>
            <Label class="sidedrawer-header-brand" text="User Name"></Label>
            <Label class="footnote" text="username@mail.com"></Label>
        </StackLayout>

        <ScrollView row="1" class="sidedrawer-content">
            <StackLayout>

                <GridLayout
                        columns="auto, *"
                        :class="'sidedrawer-list-item' + (selectedPage === page.name ? ' selected': '')"
                        v-for="(page, i) in pages"
                        :key="i"
                        @tap="goToPage(page.component)">
                    <Label col="0" :text="page.icon" class="fa"></Label>
                    <Label col="1" :text="page.name" class="p-r-10"></Label>
                </GridLayout>

            </StackLayout>
        </ScrollView>
    </GridLayout>
</template>

<script>
    import * as utils from "~/shared/utils";
    import SelectedPageService from "~/shared/selected-page-service";
    import Login from "./Login";
    import Featured from "./Featured";

    export default 
        data () 
            return 
                selectedPage: "",
                pages: [
                    
                        path: '/',
                        name: 'Home',
                        icon: "\uf015",
                        component: this.$routes.Home
                    ,
                    
                        path: '/browse',
                        name: 'Browse',
                        icon: '\uf25a',
                        component: this.$routes.Browse,
                        meta : 
                            requiresAuth: true
                        
                    ,
                    
                        path: '/featured',
                        name: 'Featured',
                        icon: '\uf005',
                        component: this.$routes.Featured
                    ,
                    
                        path: '/search',
                        name: 'Search',
                        icon: '\uf002',
                        component: this.$routes.Search
                    ,
                    
                        path: '/settings',
                        name: 'Settings',
                        icon: '\uf013',
                        component: this.$routes.Settings
                    ,
                    
                        path: '/tasks',
                        name: 'Tasks',
                        icon: '\uf0ae',
                        component: this.$routes.Tasks
                    ,
                    
                        path: '/login',
                        name: 'Login',
                        icon: '\uf007',
                        component: this.$routes.Login
                    
                ]
            ;
        ,
        mounted() 
            SelectedPageService.getInstance().selectedPage$
                .subscribe((selectedPage) => this.selectedPage = selectedPage);
        ,
        methods: 
            goToPage (pageComponent) 
                this.$navigateTo(pageComponent, 
                    clearHistory: true
                );
                utils.closeDrawer();
            ,
        ,
        computed: 
            loggedIn() 
                return this.$store.getters.loggedIn
            ,
        
    ;
</script>

如您所见,这里的路由实际上是在pages 数组中定义的,然后在上面的GridLayout 中循环。

问题在于它几乎没有摆动的空间,因为我必须处理来自循环本身的数据if(page.name === 'Login') page.name = 'Logout'

这是我最初的尝试,使用 v-if 指令。但我很快就放弃了,因为声明太长而且有点乱。

我还尝试删除循环并仅对整个菜单进行硬编码,但我无法访问标记中的this.$routes.Home

此时我真的迷路了。我愿意接受您的任何建议。

【问题讨论】:

【参考方案1】:

pages 属性设为getter,这样您就可以轻松地将push 放入数组中:

computed: 
  pages: function() 
    const pages = [
        path: '/',
        name: 'Home',
        icon: "\uf015",
        component: this.$routes.Home
      ,
      
        path: '/browse',
        name: 'Browse',
        icon: '\uf25a',
        component: this.$routes.Browse,
        meta: 
          requiresAuth: true
        
      ,
      
        path: '/featured',
        name: 'Featured',
        icon: '\uf005',
        component: this.$routes.Featured
      ,
      
        path: '/search',
        name: 'Search',
        icon: '\uf002',
        component: this.$routes.Search
      ,
      
        path: '/settings',
        name: 'Settings',
        icon: '\uf013',
        component: this.$routes.Settings
      ,
      
        path: '/tasks',
        name: 'Tasks',
        icon: '\uf0ae',
        component: this.$routes.Tasks
      ,

    ]

    if (!!this.$store.getters['loggedIn']) 
      pages.push(
        path: '/logout',
        name: 'Logout',
        icon: '....',
        component: this.$routes.Logout
      )
     else 
      pages.push(
        path: '/login',
        name: 'Login',
        icon: '\uf007',
        component: this.$routes.Login
      )
    

    return pages

  

【讨论】:

谢谢哥们。但是!!this.$store.getters['loggedIn']为什么要用双感叹号呢? @Halnex 不需要它,因为 store getter 保证一个布尔值,我怀疑这只是防御性编码

以上是关于如果用户已登录,则更改路由名称和组件的主要内容,如果未能解决你的问题,请参考以下文章

win32 检查账户是不是登录

如何更改登录路由名称

导航栏不会根据路由条件在 app.js 中呈现。路由更改时不会触发 Useeffect

Laravel 5:如果用户登录,则更改导航栏

从 Vuex 动作和组件更改路由

mac--快捷键