Is there some implementation if I want to use the main page path '/' for different views depending on roles? Like if you are an authorized user you will see the MainAuth
, if you are a guest you will see the MainGuest
? Here is some code that would help me to explain.
const routes = [
{
path: '/',
name: 'main_auth',
component: MainAuth,
meta: {
requiresAuth: true
}
},
{
path: '/',
name: 'main_guest',
component: MainGuest,
meta: {
requiresGuest: true
}
}
]
For this example, it just loads the first path I declared whatever I am a guest or user. To be more specific, I have a login/register module on the main path '/' and I want to load an authorized user page on the same path '/' after login.
Here are 3 options:
1. Simple Computed View
To allow a single route to display any number of conditional views, use a computed component.
Register views:
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)
Route:
{
path: '/',
name: 'index',
component: ViewDefault
},
View Default.vue
<template>
<component :is="view"></component>
</template>
<script>
export default {
name: 'view-default',
computed: {
view() {
return this.isAuthenticated ? 'view-auth' : 'view-guest'
}
}
}
</script>
You will be able to create as many conditional checks you want in view()
.
2. Conditional Named Views ( Concept not tried )
I would consider experimenting with the use of named views, I believe you could double view many paths with user and guest versions, not something I tried yet:
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. Computed Layouts
However ... I personally use I/O blocking layouts, computed layout
.
I check various application states that control what layouts are displayed depending on the conditions before a final layout is computed that would contain <router-view>
.
I let the router paths specify custom layouts via meta
data, set alternate layout else falls back to default layout.
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)
Only layout-default
or any router path specifying a custom layout should contain <router-view>
along with header, footer, sidebar etc...
You could mix this up with name views, different computed layouts could display a different named router-view
for the same path
.
Since you want to use only one path, you could use a basic route and do the work in the component itself. The route:
const routes = [
{
path: '/',
name: 'main',
component: Main,
}
]
Main
view component:
<template>
<div>
<Auth v-if="!loggedIn" />
<MainContent v-else />
</div>
</template>
Auth
component:
<template>
<div>
<Login v-if="showLogin" />
<Register v-else />
</div>
</template>
With this, you check if the user is logged in from the Main
view component and show either the Auth
component or the main content.
Then, in the Auth
component, you use a toggle that allows the user to switch between a Login
and Register
component.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With