web-dev-qa-db-ja.com

Vue router-ユーザーの役割に基づいて、同じルートパスに複数のコンポーネントをロードする方法は?

ユーザーがさまざまな役割でログインできるアプリがあります。 sellerbuyerおよびadmin。ユーザーごとに、同じパスにダッシュボードページを表示したいと思います。 _http://localhost:8080/dashboard_ただし、各ユーザーは、異なるvueコンポーネント、たとえばSellerDashboardBuyerDashboardおよびAdminDashboardで定義された異なるダッシュボードを持ちます。 。

したがって、基本的に、ユーザーが_http://localhost:8080/dashboard_ vueを開くと、アプリはユーザーロール(vuexに保存する)に基づいて異なるコンポーネントをロードする必要があります。同様に、これを他のたとえば、ユーザーがプロファイルページに移動すると、_http://localhost:8080/profile_アプリは、ログインしたユーザーに応じて異なるプロファイルコンポーネントを表示する必要があります。

したがって、各ユーザーの役割に異なるルートを設定するのではなく、すべてのユーザーの役割に同じルートを設定したいと考えています。次のようにユーザーロールをURLに含めたくありません:_http://localhost:8080/admin/profile_および_http://localhost:8080/seller/profile_など...

vue routerを使用してこのシナリオを実装するにはどうすればよいですか?

子ルートとルートごとのガードbeforeEnterの組み合わせを使用して、ユーザーロールに基づいたルートに解決してみました。以下はそのコードサンプルです。

in router.js

_import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import store from '@/store'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,

    beforeEnter: (to, from, next) => {
      next({ name: store.state.userRole })
    },

    children: [
      {
        path: '',
        name: 'admin',
        component: () => import('@/components/Admin/AdminDashboard')
      },
      {
        path: '',
        name: 'seller',
        component: () => import('@/components/Seller/SellerDashboard')
      },
      {
        path: '',
        name: 'buyer',
        component: () => import('@/components/Buyer/BuyerDashboard')
      }
    ]
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router
_

store.js

_import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    userRole: 'seller' // can also be 'buyer' or 'admin'
  }
})
_

App.vueには、最上位ルートの親ルータービューが含まれています。 _/_をHomeコンポーネントにマップし、_/about_をAboutコンポーネントにマップします。

_<template>
  <router-view/>
</template>

<script>
export default {
  name: 'App',
}
</script>
_

そしてHome.vueには、さまざまなユーザーの役割ベースのコンポーネント用のネストされた_router-view_が含まれています。

_<template>
  <div class="home fill-height" style="background: #ddd;">
    <h1>Home.vue</h1>
    <!-- nested router-view where user specific component should be rendered -->
    <router-view style="background: #eee" />
  </div>
</template>

<script>
export default {
  name: 'home'
}
</script>
_

しかし、beforeEnternext({ name: store.state.userRole })を呼び出すと、ブラウザーコンソールで_Maximum call stack size exceeded_例外が発生するため、機能しません。例外は次のとおりです。

_vue-router.esm.js?8c4f:2079 RangeError: Maximum call stack size exceeded
    at VueRouter.match (vue-router.esm.js?8c4f:2689)
    at HTML5History.transitionTo (vue-router.esm.js?8c4f:2033)
    at HTML5History.Push (vue-router.esm.js?8c4f:2365)
    at eval (vue-router.esm.js?8c4f:2135)
    at beforeEnter (index.js?a18c:41)
    at iterator (vue-router.esm.js?8c4f:2120)
    at step (vue-router.esm.js?8c4f:1846)
    at runQueue (vue-router.esm.js?8c4f:1854)
    at HTML5History.confirmTransition (vue-router.esm.js?8c4f:2147)
    at HTML5History.transitionTo (vue-router.esm.js?8c4f:2034)
_

したがって、何もレンダリングされません。

これを解決する方法はありますか?

6
mlst

1つのアプローチは、 動的コンポーネント を使用することです。コンポーネントが特定されていない子ルートを1つ持つこともできます(例:DashboardComponent):

router.js

const routes = [
  {
    path: '/',
    name: 'home',
    children: [
      {
        path: '',
        name: 'dashboard',
        component: () => import('@/components/Dashboard')
      }
    ]
  }
]

components/Dashboard.vue

<template>
  <!-- wherever your component goes in the layout -->
  <component :is="dashboardComponent"></component>
</template>

<script>
import AdminDashboard from '@/components/Admin/AdminDashboard'
import SellerDashboard from '@/components/Seller/SellerDashboard'
import BuyerDashboard from '@/components/Buyer/BuyerDashboard'

const RoleDashboardMapping = {
  admin: AdminDashboard,
  seller: SellerDashboard,
  buyer: BuyerDashboard
}

export default {
  data () {
    return {
      dashboardComponent: RoleDashboardMapping[this.$store.state.userRole]
    }
  }
}
</script>
0
Matt U

このようなコードは、特定のロールのコンポーネントコードのみを取得します。

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import store from "../store";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "home",
    component: () => {
      switch (store.state.userRole) {
        case "admin":
          return import("../components/AdminDashboard");
        case "buyer":
          return import("../components/BuyerDashboard");
        case "seller":
          return import("../components/SellerDashboard");
        default:
          return Home;
      }
    }
  }
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

export default router;
0
Gander

next({ name: store.state.userRole })が別のリダイレクトをトリガーしてbeforeEnterを再度呼び出し、無限ループが発生するため、_Maximum call stack size exceeded_例外が発生します。これを解決するには、toパラメータを確認します。すでに設定されている場合は、next()を呼び出してナビゲーションを確認できます。リダイレクトは行われません。以下のコードを参照してください。

_beforeEnter: (to, from, next) => {
  // Helper to inspect the params.
  console.log("to", to, "from", from)

  // this is just an example, in your case, you may need
  // to verify the value of `to.name` is not 'home' etc. 
  if (to.name) { 
    next();
  } else {
    next({ name: store.state.userRole })
  }
},
_
0
lenglei