有没有办法根据用户角色为一条路线加载不同的视图?

Is there a way to load different views for one route depending on user role?

如果我想根据角色对不同的视图使用主页路径'/',是否有一些实现?如果您是授权用户,您会看到 MainAuth,如果您是访客,您会看到 MainGuest?这是一些可以帮助我解释的代码。

const routes = [
  {
    path: '/',
    name: 'main_auth',
    component: MainAuth,
    meta: {
      requiresAuth: true
    }
  },
  {
    path: '/',
    name: 'main_guest',
    component: MainGuest,
    meta: {
      requiresGuest: true
    }
  }
]

对于这个例子,它只加载我声明的第一个路径,无论我是访客还是用户。更具体地说,我在主路径“/”上有一个 login/register 模块,我想在登录后在同一路径“/”上加载授权用户页面。

您可以使用 beforeEach 方法将用户重定向到另一条路线。

示例:

router.beforeEach((to, from, next) => {
  // Determine if the route requires Authentication
  const requiresAuth = to.matched.some(x => x.meta.requiresAuth);
  const user = auth.getUser();

  // If it does and they are not logged in, send the user to "/login"
  if (requiresAuth && !user) {
    next("/login");
  } else {
    // Else let them go to their next destination
    next();
  }
});

由于您只想使用一个路径,您可以使用一个基本路径并在组件本身中完成工作。路线:

const routes = [
  {
    path: '/',
    name: 'main',
    component: Main,
  }
]

Main 查看组件:

<template>
  <div>
    <Auth v-if="!loggedIn" />
    <MainContent v-else />
  </div>
</template>

Auth分量:

<template>
  <div>
    <Login v-if="showLogin" />
    <Register v-else />
  </div>
</template>

这样,您检查用户是否从 Main 视图组件登录并显示 Auth 组件或主要内容。

然后,在 Auth 组件中,使用允许用户在 LoginRegister 组件之间切换的开关。

这里有 3 个选项:

1.简单计算视图

要允许单个路由显示任意数量的条件视图,请使用计算组件。

注册浏览量:

import Vue from 'vue'

import ViewDefault from '/views/Default.vue'
Vue.component('view-default', ViewDefault )

import ViewAuth from '/views/Auth.vue'
Vue.component('view-auth', ViewAuth )

import ViewGuest from '/views/Guest.vue'
Vue.component('view-guest', ViewGuest)

路线:

  {
    path: '/',
    name: 'index',
    component: ViewDefault
  },

查看Default.vue

<template>
  <component :is="view"></component>
</template>

<script>

export default {

  name: 'view-default',

  computed: {

   view() {
     return this.isAuthenticated ? 'view-auth' : 'view-guest'
   }  

  }

}

</script>

您将能够在 view() 中创建任意数量的条件检查。


2。条件命名视图(概念未尝试)

我会考虑尝试使用命名视图,我相信您可以使用用户和来宾版本双重查看许多路径,但我还没有尝试过:

https://router.vuejs.org/guide/essentials/named-views.html

<template>

  <div>

    <template v-if="isAuthenticated">
      <router-view name="authed"/>
    </template>
  
    <template v-else>
      <router-view/>
    </template>

  </div>

</template>

Router


const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: MainGuest,
        authed: MainAuth,
      }
    }
  ]
})


3。计算布局

但是...我个人使用 I/O 阻塞布局,计算 layout

在计算包含 <router-view>.

的最终布局之前,我检查了各种应用程序状态,这些状态根据条件控制显示哪些布局

我让路由器路径通过 meta 数据指定自定义布局,设置备用布局,否则回退到默认布局。

Router

  {
    name: 'index',
    path: '/',
    meta: {
      title: 'Welcome',
      guard: 'auth'
    },
    component: import('@/views/welcome')
  },

  {
    name: 'settings',
    path: '/settings',
    meta: {
      title: 'Account Settings',
      layout: 'settings',
      guard: 'auth'
    },
    component:  import('@/views/account-settings')
  }

App.vue

<template>

  <div id="app" v-cloak :class="$root.layout">

    <transition name="component-fade" mode="out-in">
      <component :is="$root.layout"/>
    </transition>

  </div>

</template>

main.js


import Vue from 'vue'
import router from './router'
import store from './store'
import '@/views/layouts'
import App from './App'


// Use Vuex to store states, `axios` calls and response `interceptors` are used to `commit` computed mapped state conditions globally.

import { mapState, mapGetters } from 'vuex'

Vue.mixin({

  computed: {

    ...mapState(['user', 'isAuthenticating', 'isOffline']),

    ...mapGetters(['isAuthenticated']),

  }

})

new Vue({

  el: '#app'
  render: h => h(App),
  store,
  router,

  computed: {

    layout () { // could move this to vuex and access via mapGetters...

      if (this.isOffline) {
        return 'layout-offline'
      }

      if (this.isAuthenticating) {
        return 'layout-authenticating'
      }

      if (this.$route.meta.hasOwnProperty('guard')) {

        if(this.$route.meta.guard === 'auth' && !this.isAuthenticated) {
          return 'layout-login'
        }

      }

      // If current route has a preferred layout use it else fallback to `layout-default`
      let layout = this.$route.meta.layout || 'default'

      return `layout-${layout}`
    }

  },

})


views/layouts/index.js

import Vue from 'vue'

import LayoutOffline from './layout-offline')
import LayoutAuthenticating from './layout-authenticating')
import LayoutLogin from './layout-login')

import LayoutDefault from './layout-default')
import LayoutSettings from './layout-settings')

Vue.component('layout-offline', LayoutOffline)
Vue.component('layout-authenticating', LayoutAuthenticating)
Vue.component('layout-login', LayoutLogin)

Vue.component('layout-default', LayoutDefault)
Vue.component('layout-settings', Layoutsettings)

只有 layout-default 或任何指定自定义布局的路由器路径应包含 <router-view> 以及页眉、页脚、边栏等...

您可以将其与名称视图混合使用,不同的计算布局可能会为相同的 path.

显示不同的名称 router-view