【问题标题】:Display layout based on boolean from Vuex基于 Vuex 的布尔值的显示布局
【发布时间】:2021-11-07 02:28:17
【问题描述】:

我得到了带有 vue-router 的 Vue2 应用程序,其路由配置如下:

export default {
  path: "/",
  redirect: "/dashboard",
  component: AdminLayout,
  meta: {
    requiresAuth: true
  },
  children: [
    {
      path: "/dashboard",
      name: "Dashboard",
      component: Dashboard
    },
    {
      path: "/add/user",
      name: "InviteUser",
      component: InviteUser
    },
    {
      path: "/groups",
      name: "Groups",
      component: Groups
    },
   ...

在应用程序中,我们有两种不同类型的用户 - 管理员和普通用户。其中一些路由应该可供两者访问,但问题是用户应该根据其类型(权限)看到不同的布局 - 管理员为AdminLayout,普通用户为UserLayout

有什么方法可以根据来自 vuex 的布尔值向应用显示用户应该看到哪个模板并保持路由路径?

  • /dashboard 管理员将看到带有AdminLayout 的仪表板
  • /dashboard 上,普通用户将看到带有UserLayout 的仪表板

我的主要路由配置:

import Vue from "vue";
import VueRouter from "vue-router";

import SessionRoutes from "./session.js";
import AdminRoutes from "./admin.js";
import defaultRoutes from "./default";

Vue.use(VueRouter);

const routes = [AdminRoutes, SessionRoutes, defaultRoutes];

const router = new VueRouter({
  mode: "history",
  routes
});

export default router;

【问题讨论】:

  • 请看here
  • 这似乎不太好。
  • 这是 nuxt 处理得非常好的众多事情之一 (nuxtjs.org/docs/2.x/concepts/views#layouts)。也许这是你的一个选择。
  • 我同意,但是我用 VueCLI 完成了几乎所有应用程序,所以此时切换到 Nuxt 没有意义:/
  • 什么是 AdminLayout/UserLayout ?它们只是组件吗?如果是这样,则可以将路由数组中的组件部分作为函数并从该函数返回所需的组件。这里的关键是任何具有必填字段的函数都可以用作 Vue 组件

标签: javascript vue.js vuex vue-router


【解决方案1】:

您可以在当前页面的布局部分设置条件,例如当您使用 nuxt 时:

<script>
  export default {
      layout: (ctx) => (ctx.isAdmin ? 'adminLayout' : 'userLayout'),
  }
</script>

但我认为您不使用 Nuxt.js,我认为以下解决方案适合您的问题:

  1. 在我们的路由中使用元对象
  2. 在 app.vue 页面设置动态组件
  3. about.vue 页面的代码

    import Home from '../views/Home.vue'
    import About from '../views/About.vue'
    import LayoutA from '../layouts/LayoutA.vue'
    import LayoutB from '../layouts/LayoutB.vue'
    Vue.use(VueRouter)
    const routes = [
      {
        path: '/',
        name: 'Home',
        component: Home,
        meta: { layout: LayoutA }
      },
      {
        path: '/about',
        name: 'About',
        component: About,
        meta: { layout: LayoutB }
      }
    ]
    const router = new VueRouter({
      mode: 'history',
      base: process.env.BASE_URL,
      routes
    })
    
    export default router;
<!--app.vue page -->

<template>
  <div id="app">
    <component :is="this.$route.meta.layout || 'div'">
      <router-view />
    </component>
  </div>
</template>

<script>
export default {
  name: "App",
};
</script>


<!--about page-->
<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div>
</template>

<script>
export default {
  name: "About"
};
</script>

【讨论】:

  • 我们有两个页面的两种布局。我需要找到解决方案,根据用户权限显示具有两种布局之一的页面。
  • @BobiDaHombre。请看这个page
【解决方案2】:

要使仪表板和所有子路由使用不同的布局,您的布局必须使用the router view component。我按照这种方法在我的一个项目中使用包装器组件来处理这个问题。

摘自我的路由器配置:

…
  {
    component: MainFrame,
    name: 'main',
    path: '/',
    redirect: 'dashboard',
    children: [
      {
        alias: 'dashboard',
        component: Dashboard,
        name: 'dashboard',
        path: '', // Default child route → be equivalent to /dashboard
      },
      {
        path: "add/user",
        name: "InviteUser",
        component: InviteUser
      },
      {
        path: "groups",
        name: "Groups",
        component: Groups
      },
    ],
  },
…

MainFrame 组件中,您可以将布局包装在dynamic component 中。因此,您可以基于 Vuex getter 轻松切换布局:

MainFrame.vue

<template>
  <component :is="layout">
    <!-- you can use slots too if you like -->
  </component>
</template>

<script>
import AdminLayout from './AdminLayout'
import UserLayout from './UserLayout'

export default {
  computed: {
    layout() {
      return this.$store.getters['isAdminUser'] ? AdminLayout : UserLayout
    }
  }
}
</script>

而且你的布局必须使用&lt;router-view /&gt;。它作为所有嵌套路由的包装器,因此您只有一个地方来处理仪表板和子页面的布局:

AdminLayout.vue

<template>
  <div class="auth-view">
    <header>…</header>
    <aside>…</aside>
    <main>
      <transition name="fade" mode="out-in">
        <router-view />
      </transition>
    </main>
    <footer>…</footer>
  </div>
</template>

UserLayout.vue

<template>
  <div class="guest-view">
    <router-view />
  </div>
</template>

编辑:

这种方法也可以用于更深的嵌套。假设您的用户路由应该有另一个子路由,您可以在路由器配置上使用渲染函数中的&lt;router-view /&gt; 解决这个问题:

…
      // Let's split down user related routes
      {
        component: { render: (h) => h('router-view') },
        name: 'usersView',
        path: 'users',
        redirect: 'ListUsers',
        children: [
          // Show users
          {
            path: '', // route: /users/
            name: 'ListUsers',
            component: ListUsers
          },
          // Show a single user
          {
            path: ':id', // route: /users/{userId}
            name: 'ViewUser',
            component: ViewUser
          },
          // Invite new users
          {
            path: 'add', // route: /users/add
            name: 'InviteUser',
            component: InviteUser
          },
        ]
      }
…

【讨论】:

  • 这让我在每一页上都添加了这段代码。效率不高
  • @BobiDaHombre 我明白了。所以我用更复杂的答案更新了我的答案,但这应该会以更好的方式满足您的期望。
猜你喜欢
  • 2021-12-23
  • 1970-01-01
  • 2020-07-29
  • 2021-06-07
  • 1970-01-01
  • 2011-06-26
  • 2015-12-21
  • 1970-01-01
  • 2012-11-11
相关资源
最近更新 更多