最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin3浏览0评论

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',
    ponent: MainAuth,
    meta: {
      requiresAuth: true
    }
  },
  {
    path: '/',
    name: 'main_guest',
    ponent: 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.

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',
    ponent: MainAuth,
    meta: {
      requiresAuth: true
    }
  },
  {
    path: '/',
    name: 'main_guest',
    ponent: 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.

Share Improve this question edited Apr 1, 2020 at 20:36 Dan 63.1k18 gold badges110 silver badges119 bronze badges asked Mar 31, 2020 at 21:14 fitzimafitzima 792 silver badges6 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 6

Here are 3 options:

1. Simple Computed View

To allow a single route to display any number of conditional views, use a puted ponent.

Register views:

import Vue from 'vue'

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

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

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

Route:

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

View Default.vue

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

<script>

export default {

  name: 'view-default',

  puted: {

   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/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: '/',
      ponents: {
        default: MainGuest,
        authed: MainAuth,
      }
    }
  ]
})

3. Computed Layouts

However ... I personally use I/O blocking layouts, puted layout.

I check various application states that control what layouts are displayed depending on the conditions before a final layout is puted 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: 'Wele',
      guard: 'auth'
    },
    ponent: import('@/views/wele')
  },

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

App.vue

<template>

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

    <transition name="ponent-fade" mode="out-in">
      <ponent :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 `mit` puted mapped state conditions globally.

import { mapState, mapGetters } from 'vuex'

Vue.mixin({

  puted: {

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

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

  }

})

new Vue({

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

  puted: {

    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.ponent('layout-offline', LayoutOffline)
Vue.ponent('layout-authenticating', LayoutAuthenticating)
Vue.ponent('layout-login', LayoutLogin)

Vue.ponent('layout-default', LayoutDefault)
Vue.ponent('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 puted 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 ponent itself. The route:

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

Main view ponent:

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

Auth ponent:

<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 ponent and show either the Auth ponent or the main content.

Then, in the Auth ponent, you use a toggle that allows the user to switch between a Login and Register ponent.

You can redirect the user to another route using the beforeEach method.

Example :

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();
  }
});
发布评论

评论列表(0)

  1. 暂无评论