This is the 17th day of my participation in the August Text Challenge.More challenges in August

background

Vue-router tends to do more work in an administrative backend system.

Because in the management background, a very important and very common function, is the distinction of user rights. General users, administrative users, super administrators, audit users and so on.

For different users, we should not only check the interface, but also divide the permissions of the page.

Such as:

  • The super administrator has all permissions, can view all pages, can perform all operations
  • Manage user, cannot add, delete, change the user in the system
  • Audit users can only view the content to be audited, such as system operation logs

All of the above, in fact, are strongly related to the display of the page, the access of the route and the verification of the interface. If the current user is an audit user, only some pages can be displayed, and if the current user is an administrative user, some pages can be hidden.

In addition, each managed project has a set of sidebars that serve as entry points to different functional pages.

Assuming that our routing and sidebar are separate logic, there are the following problems:

  • Every time you update a route, you update the sidebar,
  • Route in the permission, the sidebar also separately add a permission management logic

This will make our front-end development look dull.

So in summary, vue-Router should achieve such functions

  • Mount the component to the page
  • Manage route permissions based on different user roles, such as super administrator, audit user, and common user
  • Generate complex sidebars based on routes

So how do you use a defined set of routers to meet these three requirements?

Analysis of the

First of all, let’s make a detailed analysis of the specific needs of these three requirements

Mount components to the page

Needless to say, vue-Router does just that

Distinguish user roles

User roles are generally saved in the database and returned by the background interface after the user logs in. For example, this field is user_Role. How can dynamic route discrimination be implemented?

  • First, we can store this field in vuEX so that it can be accessed globally and automatically updated globally
  • Second, insert a field in each of the vue-Router’s routing objects, such as callpermissionTo record who can access the current route, such asPermission: [0]
  • According to theuser_roleandpermissionTo match all the filtered routes. The filtered result is the route that the current user can access
  • Add the resulting route to the project’s routing object, address, using vue-router

Generate complex sidebars

The sidebar is the functionality that is available in the admin background, and here refer to the vue-element-admin implementation. The Router is essentially a javascript array object that can be iterated over using elementUi’s El-Menu component to generate the sidebar.

If the router changes, the sidebar changes with it.

implementation

We define an overall Router object. This object is the route of all the pages in the project and is also the default access permission of the super administrator. Each route object of this object can contain the following properties or methods:

  • Hidden: Whether to display in the sidebar
  • Name: indicates the text content corresponding to the sidebar. If name does not exist, the route in children is a level-1 route; otherwise, it is a level-2 route. The sidebar displays a maximum of level-2 routes
  • IconName: Icon icon in the sidebar
  • Permission: List of users that can access the address route
// routerData.js
const router1 = [
  {
    path: '/'.redirect: '/homepage'.hidden: true.meta: { permission: [1.2.3]}}, {path: '/homepage'.meta: { permission: [1.2.3]},redirect: '/homepage/dashboard'.component: layout,
    children: [{path: 'dashboard'.name: 'Security status Monitoring'.meta: { iconName: 'icon-erji-loudongsaomiaoguanli'.permission: [1.2.3]},component: () = > import('.. /views/dashboard/index.vue'),},]}, {path: '/assetManagement'.name: 'Asset Management'.meta: { iconName: 'icon-erji-loudongsaomiaoguanli'.permission: [1.2.3]},redirect: '/assetManagement/assetList'.component: layout,
    children: [{path: 'assetList'.name: 'Asset List'.meta: { permission: [1.2.3]},component: () = > import('.. /views/assetManagement/assetList.vue'),}, {path: 'assetDetail'.name: 'Details of Assets'.meta: { permission: [1.2.3]},component: () = > import('.. /views/assetManagement/assetList.vue'),},]}, {path: The '*'.redirect: '/'.hidden: true.meta: { permission: [1.2.3]}}]export commonRoute = [{ 
    path: '/login'.component: () = > import('@/views/login.vue'), 
    hidden: true.meta: { permission: [1.2.3]}}]export default router1
Copy the code

We then mount the router in index.js

// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import { commonRoute } from './routerData'
import layout from '@/layout'

Vue.use(VueRouter)

export const permissionRouter = function(router, roleType) {
  return router.filter(item= > {
    if(item.children)
      item.children = permissionRouter(item.children)
    return item.meta.permission.includes(roleType)
  })
}

export default new VueRouter({
  commonRoute
})
Copy the code

After the user logs in, we first obtain the user’s role and store it in VUEX. Then, we can dynamically calculate the permission route according to the user’s role

import store from '@/store'
import router1  from '@/router/routerData'
import router, {permissionRouter} from '@/router/index'

const roleType = store.getters.user_role
const permissionRouterList = permissionRouter(router1, roleType)

router.addRoute(permissionRouterList)

Copy the code

The router is ready to dynamically generate the sidebar. The sidebar logic is a little more complicated, so I split it into three files

Here is the directory for the files:

Sidebar Exercises ─ Index. Vue Exercises ─ item. Vue Exercises ─ Sidebar ItemCopy the code

Then implement the logic of the dynamic sidebar

// index.vue
<template>
  <div class="sidebar-container">
    <el-menu :unique-opened="true"
             :collapse-transition="false"
             background-color="Rgba (0,0,0,0)"
             :default-active="activeMenu">
      <sidebar-item v-for="(item, index) in permissionRouterList"
                    :key="index"
                    :item="item" />
    </el-menu>
  </div>
</template>
<script>
import store from '@/store'
import router1  from '@/router/routerData'
import {permissionRouter} from '@/router/index'
import SidebarItem from './sidebarItem.vue'
export default {
  components: {
    SidebarItem
  },
  computed: {
    activeMenu() {
      return this.$route.path
    },
    permissionRouterList(){
        const roleType = store.getters.user_role
        return permissionRouter(router1, roleType)
    }
  }
}
</script>
Copy the code
// item.vue
<template>
  <el-menu-item :index="compilePath(child.path)"
                @click="clickEvent(child)"
                v-if=! "" child.hidden">
    <i v-if="child.meta"
       class="iconfont"
       :class="child.meta.iconName"></i>
    <span slot="title">{{child.name}}</span>
  </el-menu-item>
</template>

<script>
import path from 'path'
export default {
  props: {
    child: {
      type: Object
    },
    basePath: {type: String}},methods: {
    compilePath(childpath) {
      return path.resolve(this.basePath, childpath)
    },
    clickEvent(child) {
      const path = this.compilePath(child.path)
      this.$router.push(path)
    }
  }
}
</script>
Copy the code
// sidebarItem.vue
<template>
  <el-submenu v-if="(item.children && hasName(item)) && ! item.hidden"
              :index="item.path">
    <template slot="title">
      <i v-if="item.meta"
         class="iconfont"
         :class="item.meta.iconName"></i>
      <span slot="title">{{item.name}}</span>
    </template>
    <menu-item v-for="child in item.children"
               :key="compilePath(item.path,child.path)"
               :child="child"
               :basePath="item.path" />
  </el-submenu>
  <menu-item :child="item.children[0]"
             v-else-if="item.children && ! item.hidden"
             :basePath="item.path" />
</template>

<script>
import path from 'path'
import MenuItem from './item.vue'
export default {
  props: {
    item: {
      type: Object}},components: {
    MenuItem
  },
  methods: {
    compilePath(itempath, childpath) {
      return path.resolve(itempath, childpath)
    },
    hasName(item){
        return item.name? true: false}}}</script>
Copy the code

In this way, our entire requirements are completed, and then the sidebar component is normally introduced, add their own style, it is ok

Finally, the code is not tested, if you have any questions please write or comment, thank you.