有没有办法根据用户角色为一条路线加载不同的视图?
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
组件中,使用允许用户在 Login
和 Register
组件之间切换的开关。
这里有 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
如果我想根据角色对不同的视图使用主页路径'/',是否有一些实现?如果您是授权用户,您会看到 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
组件中,使用允许用户在 Login
和 Register
组件之间切换的开关。
这里有 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