Javascript Vue路由器-如何根据用户角色在同一路由路径上加载多个组件?

Javascript Vue路由器-如何根据用户角色在同一路由路径上加载多个组件?,javascript,vue.js,vuex,vue-router,Javascript,Vue.js,Vuex,Vue Router,我有一个应用程序,用户可以以不同的角色登录,例如卖家,买家和管理员。 对于每个用户,我希望在同一路径上显示仪表板页面,例如http://localhost:8080/dashboard 但是,每个用户将在不同的vue组件中定义不同的仪表板,例如,SellerDashboard、BuyerDashboard和AdminDashboard 所以基本上,当用户打开http://localhost:8080/dashboardvue应用程序应根据用户角色(我存储在vuex中)加载不同的组件。类似地,我希

我有一个应用程序,用户可以以不同的角色登录,例如
卖家
买家
管理员
。 对于每个用户,我希望在同一路径上显示仪表板页面,例如
http://localhost:8080/dashboard
但是,每个用户将在不同的vue组件中定义不同的仪表板,例如,
SellerDashboard
BuyerDashboard
AdminDashboard

所以基本上,当用户打开
http://localhost:8080/dashboard
vue应用程序应根据用户角色(我存储在vuex中)加载不同的组件。类似地,我希望其他路线也有这个。例如,当用户转到配置文件页面
http://localhost:8080/profile
根据登录用户的不同,应用程序应显示不同的配置文件组件

因此,我希望所有用户角色都有相同的路由,而不是每个用户角色都有不同的路由,例如,我不希望用户角色包含在url中,如下所示:
http://localhost:8080/admin/profile
http://localhost:8080/seller/profile

如何使用vue路由器实现此方案

我尝试在输入前使用子路由和每个路由保护的组合来解析基于用户角色的路由。下面是一个代码示例:

在路由器.js中:

从“Vue”导入Vue
从“vue路由器”导入VueRouter
从“../views/Home.vue”导入主页
从“@/store”导入存储
Vue.use(VueRouter)
常数路由=[
{
路径:“/”,
姓名:'家',
组成部分:家庭,
beforeEnter:(到、从、下一个)=>{
下一步({name:store.state.userRole})
},
儿童:[
{
路径:“”,
名称:'管理员',
组件:()=>导入('@/components/Admin/AdminDashboard')
},
{
路径:“”,
名称:'卖方',
组件:()=>导入(“@/components/Seller/SellerDashboard”)
},
{
路径:“”,
名称:'买方',
组件:()=>导入(“@/components/Buyer/BuyerDashboard”)
}
]
},
]
常量路由器=新的VueRouter({
模式:“历史”,
base:process.env.base\u URL,
路线
})
导出默认路由器
在store.js中:

从“Vue”导入Vue
从“Vuex”导入Vuex
Vue.use(Vuex)
导出默认的新Vuex.Store({
声明:{
userRole:'卖方'//也可以是'买方'或'管理员'
}
})
App.vue包含顶级路由的父路由器视图,例如将
/
映射到
Home
组件和
/about
映射到
about
组件:


导出默认值{
名称:“应用程序”,
}
Home.vue包含嵌套的
路由器视图
,用于不同用户基于角色的组件:


Home.vue
导出默认值{
姓名:“家”
}
但它不起作用,因为当我在进入前调用
中的
next({name:store.state.userRole})
时,浏览器控制台中出现了
超过最大调用堆栈大小的异常。例外情况是:

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)
因此什么也没有呈现


有什么方法可以解决这个问题吗?

一种方法是使用。您可以有一个子路由,其组件也是非特定的(例如,
仪表板组件
):

router.js

const路由=[
{
路径:“/”,
姓名:'家',
儿童:[
{
路径:“”,
名称:“仪表板”,
组件:()=>导入(“@/components/Dashboard”)
}
]
}
]
组件/仪表板.vue


从“@/components/Admin/AdminDashboard”导入AdminDashboard
从“@/components/Seller/SellerDashboard”导入SellerDashboard
从“@/components/Buyer/BuyerDashboard”导入BuyerDashboard
常量RoleDashboardMapping={
管理员:AdminDashboard,
卖家:SellerDashboard,
买方:买方仪表板
}
导出默认值{
数据(){
返回{
仪表板组件:RoleDashboardMapping[此.$store.state.userRole]
}
}
}

您可能希望尝试以下解决方案:

<template>
  <component :is="compName">
</template>
data: () {
 return {
      role: 'seller' //insert role here - maybe on `created()` or wherever
 }
},
components: {
 seller: () => import('/components/seller'),
 admin: () => import('/components/admin'),
 buyer: () => import('/components/buyer'),
}

数据:(){
返回{
角色:'seller'//在此处插入角色-可能在'created()'上或任何地方
}
},
组成部分:{
卖方:()=>进口('/components/seller'),
管理员:()=>导入('/components/admin'),
买方:()=>进口('/components/buyer'),
}
或者,如果您更喜欢整洁一点(相同的结果):


数据:()=>({compName:'seller'}),
计算:{
loadComp(){
const compName=this.compName
return()=>import(`/components/${compName}`)
}
}

这将允许您使用动态组件,而不必预先导入所有的CMP,但每次只使用所需的一个。

您遇到
最大调用堆栈大小超过了
异常,因为
下一个({name:store.state.userRole})
将触发另一个重定向,并在再次进入之前调用
,从而导致无限循环。 要解决此问题,您可以检查
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 })
  }
},

解决此问题的一种方法是为三种类型的用户创建三个单独的组件
DashboardForAdmin
DashBoardForSeller
,以及
DashBoardForBuyer

然后使用mixin.js

export default {
    data: function () {
        return {
          userType : "buyer"; // replace this with a function that returns "seller", "buyer", or "admin"
        }
    }
}
创建Vue组件
仪表板容器
根据mixin返回值呈现正确的仪表板组件

    <template>
        <div>
            <div v-if="userType === 'admin'">
                <DashboardForAdmin />
            </div>
            <div v-else-if="userType === 'buyer'">
                <DashboardForBuyer />
            </div>
            <div v-else>
                <DashboardForSeller />
            </div>
        </div>
    </template>

    <script>
        import mixin from '@/mixin.js';

        import DashboardForAdmin from '@/components/DashboardForAdmin.vue';
        import DashBoardForSeller from '@/components/DashBoardForSeller.vue';
        import DashBoardForBuyer from '@/components/DashBoardForBuyer.vue';

        export default {
            mixins: [mixin],
            components: {
                DashboardForAdmin, DashBoardForSeller, DashBoardForBuyer 
            },
        };
    </script>

从“@/mixin.js”导入mixin;
从“@/components/DashboardForAdmin.vue”导入DashboardForAdmin;
导入仪表板用于卖方f
    <template>
        <div>
            <div v-if="userType === 'admin'">
                <DashboardForAdmin />
            </div>
            <div v-else-if="userType === 'buyer'">
                <DashboardForBuyer />
            </div>
            <div v-else>
                <DashboardForSeller />
            </div>
        </div>
    </template>

    <script>
        import mixin from '@/mixin.js';

        import DashboardForAdmin from '@/components/DashboardForAdmin.vue';
        import DashBoardForSeller from '@/components/DashBoardForSeller.vue';
        import DashBoardForBuyer from '@/components/DashBoardForBuyer.vue';

        export default {
            mixins: [mixin],
            components: {
                DashboardForAdmin, DashBoardForSeller, DashBoardForBuyer 
            },
        };
    </script>
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import AdminDashboard from "../components/AdminDashboard";
import BuyerDashboard from "../components/BuyerDashboard";
import SellerDashboard from "../components/SellerDashboard";
import store from "../store";

Vue.use(VueRouter);

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

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

export default router;