最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue如何根據(jù)權(quán)限生成動態(tài)路由、導(dǎo)航欄

 更新時間:2022年03月30日 11:31:47   作者:秋刀魚笛滋味  
這篇文章主要介紹了vue如何根據(jù)權(quán)限生成動態(tài)路由、導(dǎo)航欄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

基本思路

1、創(chuàng)建vueRouter,用公共路由實例化

2、創(chuàng)建需要根據(jù)權(quán)限篩選的路由對象(在路由對象,添加必要的權(quán)限判斷字段)

3、登錄完成,由后端配合返回當(dāng)前用戶的權(quán)限集合

4、篩選出有權(quán)限的路由對象,利用vueRouter的addRoutes方法,生成完整路由

5、處理刷新頁面導(dǎo)致vueRouter重新實例化導(dǎo)致路由對象不完善 (利用router.beforeEach導(dǎo)航守衛(wèi),,利用addRoutes()完善 路由對象 )

6、側(cè)邊導(dǎo)航欄相關(guān)代碼

相關(guān)代碼

根據(jù)上面的順序

1、如下

Vue.use(Router)
// 公共路由
export const publicRoutes = [
  {
    path: '/',
    name: 'login',
    component: login,
    meta: {
      title: '登錄'
    }
  }
]
// 需要根據(jù)權(quán)限篩選的路由
export const asyncRoutes = [
  ...Home,
  ...Seting,
  ...CRM,
  {
    path: '*',
    component: login,
    meta: {
      hidden: true
    },
    redirect: '/'
  }
]
const vr = new Router({
  mode: 'history',
  routes: publicRoutes
})

2、以seting模塊為例,role為判斷是的權(quán)限字段,角色有這個字段對應(yīng)的值就有當(dāng)前頁面的權(quán)限

import Layout from '@/views/layout/layout.vue'
const account = r => require.ensure([], () => r(require('@/views/seting/account/account.vue')), 'seting');
const logs = r => require.ensure([], () => r(require('@/views/seting/logs/logs.vue')), 'seting');
const role = r => require.ensure([], () => r(require('@/views/seting/role/role.vue')), 'seting');
const Seting = [
  {
    path: '/seting',
    component: Layout,
    redirect: '/seting/account',
    meta: {
      title: '系統(tǒng)設(shè)置',
      role: '123c6c6514d416472e640bc3f49297c550',
      icon: 'icon-xitong'
    },
    children: [
      {
        path: 'account',
        name: 'account',
        component: account,
        meta: {
          title: '賬號管理',
          role: '1325cdeb897cc7f8e951d647de9b1d8e11',
        }
      },
      {
        path: 'logs',
        name: 'logs',
        component: logs,
        meta: {
          title: '日志管理',
          role: '14bfbb0337ad3e7e2c9fc101294c3fe645',
        }
      },
      {
        path: 'role',
        name: 'role',
        component: role,
        meta: {
          title: '角色管理',
          role: '1559d1c05d15a0dce5549b8bf5a58c0cf9',
        }
      }
    ]
  }
]
export default Seting

如果有一些詳情頁不需要在導(dǎo)航列表展示還可以添加字段,在生成導(dǎo)航欄時去掉

eg:

 {
            path: 'addJoiner',
            name: 'addJoiner',
            component: addJoiner,
            meta: {
              hidden: true,  // 隱藏字段
              title: '***詳情頁',
              role: '14bfbb0337ad3e7e2c9fc101294c3fe645',
            }
          },

3、登錄獲取權(quán)限集合和基本信息

 // 登錄
    login () {
      this.rememberPassword()
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.loading = true
          let params = {
            login_name: this.form.user,
            password: this.form.password,
            code: this.form.yanzhenma,
          }
          this.$api.post('api/user/login', params).then(res => {
            if (res.err_code === 1) {
              // 把用戶的基本信息儲存在vuex,中
              this.$store.dispatch('setBaseInfo', res.data).then(() => {
                // 獲取有權(quán)限的路由表,添加到路由
                router.addRoutes(this.$store.getters.addRouters)
                this.$router.push({ name: 'home' })
              })
            }
            this.loading = false
          })
        }
      })

部分vuex代碼

如果不太理解,點擊下面鏈接:

vuex刷新就沒了解決方案

秒懂vuex

actions.js

// import api from '@/api'
const actions = {
  setBaseInfo ({
    commit
  }, data) {
    return new Promise(resolve => {
      commit('set_userInfo', data.userInfo)
      commit('set_token', data.token)
      commit('set_roles', data.menus)
      // 把基本信息保存在本地防止刷新之后丟失
      sessionStorage.setItem('baseInfo', JSON.stringify(data))
      resolve()
    })
  }
}
export default actions

mutations.js

const setStorage = (key, value) => {
  if (typeof (value) === 'object') {
    value = JSON.stringify(value)
  }
  sessionStorage.setItem(key, value)
}
/*
* 避免刷新之后vuex被重置,在sessionStorage做一個備份
 */
const mutations = {
  set_userInfo (state, payload) {
    state.userInfo = payload
    setStorage('userInfo', payload)
  },
  set_token (state, payload) {
    state.token = payload
    setStorage('token', payload)
  },
  set_roles (state, payload) {
    state.roles = payload
    setStorage('roles', payload)
  },
  set_breadcrumb (state, payload) {
    state.breadcrumb = payload
    setStorage('breadcrumb', payload)/*  */
  },
  changeCollapsed (state, payload) {
    state.isCollapsed = payload
  }
}
export default mutations

getters.js

import createdRoutes from '@/utils/createdRoutes.js'
import { asyncRoutes } from '@/router/index.js'
let getStoryage = (item) => {
  let str = sessionStorage.getItem(item)
  return JSON.parse(str)
}
const getters = {
  get_userInfo: (state) => {
    return state.userInfo ? state.userInfo : getStoryage('userInfo')
  },
  get_token: (state) => {
    return state.token ? state.token : sessionStorage.getItem('token')
  },
  get_roles: (state) => {
    return state.roles.length ? state.roles : getStoryage('roles')
  },
  addRouters: (state, getters) => {
    let routes = createdRoutes(asyncRoutes, getters.get_roles)
    return routes
  },
  get_breadcrumb: (state, getters) => {
    return state.breadcrumb.length ? state.breadcrumb : getStoryage('getStoryage')
  }
}
export default getters;

4、核心的篩選需要權(quán)限的路由方法:createdRoutes()

也就是3的getters,用到的方法,毫無保留奉上

/**
 * 判單當(dāng)前的路由對象是否在登錄人的權(quán)限之內(nèi)
 * @param {Array} roles 權(quán)限
 * @param {Object} route 路由
 */
function hasPermission (roles, route) {
  if (route.meta && route.meta.role) { // 路由需要權(quán)限就要在權(quán)限數(shù)組里面判斷
    return roles.includes(route.meta.role)
  } else { // 不需要權(quán)限就直接通過
    return true
  }
}
/**
 * 根據(jù)接口獲取的權(quán)限列表動態(tài)生成當(dāng)前用戶的側(cè)邊導(dǎo)航欄,返回通過權(quán)限驗證的路由數(shù)組
 * @param {Array} asyncRoutes 需要過濾的路由
 * @param {Array} roles 權(quán)限
 */
function createdRoutes (asyncRoutes, roles) {
  const accessedRouters = asyncRoutes.filter(route => {
    if (hasPermission(roles, route)) { // 當(dāng)前路由通過權(quán)限驗證直接通過
      if (route.children && route.children.length) { // 當(dāng)前路由有子路由,就遞歸驗證
        route.children = createdRoutes(route.children, roles)
      }
      return true
    }
    return false
  })
  return accessedRouters
}
export default createdRoutes

5、處理刷新帶來的問題

其實這里的代碼是連接1的,注意注釋

// 全局的導(dǎo)航守衛(wèi)
vr.beforeEach((to, from, next) => {
  // 刷新頁面之后導(dǎo)致vue-router和vuex重置,路由丟失,利用的就是刷新后vuex的state被重置判斷
  if (to.name !== 'login' && !store.state.token) {
    // 避免直接不登陸進頁面
    if (!sessionStorage.getItem('token')) {
      location.href = '/'
      return
    }
    let data = JSON.parse(sessionStorage.getItem('baseInfo'))
    store.dispatch('setBaseInfo', data).then(() => {
      vr.addRoutes(store.getters.addRouters)
    })
  }
  // 設(shè)置面包屑導(dǎo)航
  let breadcrumb = to.matched.filter(item => item.meta.title)
  if (breadcrumb.length) {
    breadcrumb = breadcrumb.map(item => item.meta.title)
    store.commit('set_breadcrumb', breadcrumb)
  }
  // 設(shè)置title
  document.title = to.meta.title
  next()
})

6、側(cè)邊導(dǎo)航欄的完整代碼

還是遍歷的根據(jù)權(quán)限生成的路由表,干掉一些需要隱藏的詳情頁之類, 

這里的代碼和過濾l路由的核心函數(shù),要根據(jù)自己的業(yè)務(wù)做相應(yīng)的處理

element-ui的menu

<template>
  <el-menu class="el-menu-vertical-demo" :collapse="isCollapsed" background-color="#545c64" :default-active='activeIndex' text-color="#fff" active-text-color="#7EA8F5">
    <section v-for="(item,index) in addRouters" :key="item.name" :class="isCollapsed ? 'collapsed':''">
      <!-- 有子菜單 -->
      <el-submenu :index=" `${index+1}`" v-if="!item.meta.hidden && item.children && item.children.length">
        <template slot="title">
          <i :class="`icon iconfont ${item.meta.icon}`"></i>
          <span slot="title">{{item.meta.title}}</span>
        </template>
        <section v-for="(item2,index2) in item.children" :key="item2.name">
          <!-- 二級菜單有子菜單 -->
          <el-submenu :index="`${index+1}-${index2+1}`" v-if="item2.children && item2.children.length" class="sub2">
            <template slot="title">
              <span slot="title">{{item2.meta.title}}</span>
            </template>
            <!-- 三級菜單 -->
            <el-menu-item v-for="(item3,index3) in item2.children" v-if="!item3.meta.hidden" :index="item3.name" :key="index3" @click.native="$router.push({name:item3.name})">
              <span slot="title">{{item3.meta.title}}</span>
            </el-menu-item>
          </el-submenu>
          <!-- 二級菜單無子菜單 -->
          <!-- 不是隱藏的,詳情頁隱藏 -->
          <el-menu-item :index="item2.name" v-else-if="!item2.meta.hidden" @click.native="$router.push({name:item2.name})">
            <span slot="title">{{item2.meta.title}}</span>
          </el-menu-item>
        </section>
      </el-submenu>
      <!-- 無子菜單 -->
      <el-menu-item v-else-if="item.meta.hidden && item.children && item.children.length" :index="item.children[0].name" @click.native="$router.push({name:item.children[0].name})" class="item">
        <i :class="`iconfont ${item.children[0].meta.icon}`"></i>
        <span slot="title">{{item.children[0].meta.title}}</span>
      </el-menu-item>
    </section>
  </el-menu>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
  props: {
    isCollapsed: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    ...mapGetters(['addRouters']),
    activeIndex () { //集火的菜單
      return this.$route.name
    }
  }
}
</script>
<style lang="scss" scoped>
section {
  /deep/ .el-submenu__title {
    .icon {
      margin-right: 10px;
    }
    i {
      color: white;
      font-size: 14px;
    }
  }
  /deep/ .el-menu-item {
    padding-left: 50px !important;
  }
  /deep/ .el-menu-item.item {
    padding-left: 19px !important;
    i {
      color: white;
      font-size: 14px;
      margin-right: 12px;
    }
  }
  /deep/ .el-submenu .el-menu-item {
    min-width: 0;
  }
  /deep/ .el-submenu.sub2 .el-submenu__title {
    padding-left: 50px !important;
    i {
      margin-right: 0px;
    }
  }
  /*   /deep/ .el-submenu.sub2 .el-menu-item {
    text-indent: 12px;
  } */
}
.collapsed {
  width: 50px;
  /deep/ .el-submenu__title {
    .el-icon-arrow-right {
      display: none;
    }
    span[slot="title"] {
      display: none;
    }
  }
}
</style>

路由圖

在這里插入圖片描述

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • Vue3中?引入Ant?Design的操作方法

    Vue3中?引入Ant?Design的操作方法

    Ant?Design?是一個開源庫,可讓您創(chuàng)建吸引人的響應(yīng)式網(wǎng)站。如果您想使用經(jīng)過充分測試且易于學(xué)習(xí)的框架,那么它是您下一個項目的絕佳選擇,這篇文章主要介紹了如何在?Vue?3?中使用?Ant?Design,需要的朋友可以參考下
    2023-04-04
  • 圖文講解用vue-cli腳手架創(chuàng)建vue項目步驟

    圖文講解用vue-cli腳手架創(chuàng)建vue項目步驟

    本次小編給大家?guī)淼氖顷P(guān)于用vue-cli腳手架創(chuàng)建vue項目步驟講解內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2019-02-02
  • vue.js移動數(shù)組位置,同時更新視圖的方法

    vue.js移動數(shù)組位置,同時更新視圖的方法

    下面小編就為大家分享一篇vue.js移動數(shù)組位置,同時更新視圖的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue $nextTick實現(xiàn)原理深入詳解

    vue $nextTick實現(xiàn)原理深入詳解

    這篇文章主要介紹了vue $nextTick實現(xiàn)原理深入詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • vue如何引入sass全局變量

    vue如何引入sass全局變量

    sass或者less都提供變量設(shè)置,在需求切換主題的項目中使用less或者sass變量,這篇文章主要介紹了vue引入sass全局變量,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • vue3.0中setup使用(兩種用法)

    vue3.0中setup使用(兩種用法)

    這篇文章主要介紹了vue3.0中setup使用,本文通過兩種用法給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • vue-cli2.x舊版本卸載不掉的問題踩坑指南(附Vue腳手架安裝教程)

    vue-cli2.x舊版本卸載不掉的問題踩坑指南(附Vue腳手架安裝教程)

    遇到一個Vuecli2腳手架卸載不了的問題,查了許多資料說的都比較復(fù)雜,所以下面這篇文章主要給大家介紹了關(guān)于vue-cli2.x舊版本卸載不掉的問題踩坑的相關(guān)資料,文中還附了Vue腳手架安裝教程,需要的朋友可以參考下
    2022-07-07
  • Vue中禁止編輯的常見方法(以禁止編輯輸入框為例)

    Vue中禁止編輯的常見方法(以禁止編輯輸入框為例)

    在我們開發(fā)項目的時候,有時候我們不希望用戶對我們的頁面進行操作,尤其是輸入框之類的,這篇文章主要給大家介紹了Vue中禁止編輯的常見方法,文中介紹的方法主要以禁止編輯輸入框為例,需要的朋友可以參考下
    2024-02-02
  • Vue keep-alive實踐總結(jié)(推薦)

    Vue keep-alive實踐總結(jié)(推薦)

    本篇文章主要介紹了Vue keep-alive實踐總結(jié)(推薦),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • vue keep-alive實現(xiàn)多組件嵌套中個別組件存活不銷毀的操作

    vue keep-alive實現(xiàn)多組件嵌套中個別組件存活不銷毀的操作

    這篇文章主要介紹了vue keep-alive實現(xiàn)多組件嵌套中個別組件存活不銷毀的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10

最新評論

如皋市| 台东县| 南宁市| 娄烦县| 澜沧| 大邑县| 图们市| 衡阳县| 陇川县| 丹东市| 富顺县| 昌黎县| 金溪县| 揭东县| 洛川县| 乐平市| 濉溪县| 晋江市| 柳州市| 隆回县| 新宁县| 方城县| 新安县| 桂东县| 嘉禾县| 泰兴市| 诸暨市| 彩票| 安溪县| 沂南县| 黑河市| 故城县| 沿河| 千阳县| 永川市| 茂名市| 泰和县| 巴林右旗| 敦化市| 保亭| 图片|