亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue addRoutes實(shí)現(xiàn)動(dòng)態(tài)權(quán)限路由菜單的示例

 更新時(shí)間:2018年05月15日 11:22:59   作者:巴謝爾托夫斯基  
本篇文章主要介紹了vue addRoutes實(shí)現(xiàn)動(dòng)態(tài)權(quán)限路由菜單的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

需求

最近接手一個(gè)后臺(tái)管理系統(tǒng),需要實(shí)現(xiàn)導(dǎo)航菜單從后臺(tái)拉取的效果;根據(jù)登錄用戶的權(quán)限不同分別拉出來的導(dǎo)航菜單也不一樣,另外可操作的界面也存在區(qū)別。

問題

因?yàn)楹笈_(tái)管理系統(tǒng)是準(zhǔn)備使用vue+vue-router+element-ui+vuex的搭配來做的,可是單頁應(yīng)用在進(jìn)入頁面之前就已經(jīng)將vue-router實(shí)例化并且注入vue實(shí)例中了,所以在進(jìn)入登錄頁面的時(shí)候舊沒辦法在重新定制路由了。接下來各種百之谷之,發(fā)現(xiàn)vue-router在2.0版本中提供了addRoutes方法添加路由,希望的曙光出現(xiàn)。

經(jīng)過一番折騰終于實(shí)現(xiàn)了功能,記錄下來便于回顧,也希望能幫助到同樣有需求的同志。

思路

1、首先在本地配置好固定不變的路由地址,例如登錄,404這些頁面,如下:

import Vue from 'vue'
import Router from 'vue-router'
import store from '@/vuex/store'
Vue.use(Router)

let router = new Router({
 routes: [
  {
   path: '/login',
   name: 'login',
   meta: {requireAuth: false},
   // 模塊使用異步加載
   component: (resolve) => require(['../components/login/login.vue'], resolve)
  }]
})
// 攔截登錄,token驗(yàn)證
router.beforeEach((to, from, next) => {
 if (to.meta.requireAuth === undefined) {
  if (store.state.token) {
   next()
  } else {
   next({
    path: '/login'
   })
  }
 } else {
  next()
 }
})
export default router

配置好這些固定的路由后我們才能夠到登錄頁面,不然是無法繼續(xù)下去的。

2、然后重要的一步,我們需要跟后端老鐵約定好需要返回的權(quán)限菜單列表信息;首先這里我們先分析一下自己需要的路由結(jié)構(gòu),這里以我自己的路由作為例子。如果是我自己直接定義路由的話,會(huì)是以下結(jié)構(gòu):

let router = new Router({
 routes: [
  {
   path: '/login',
   name: 'login',
   meta: {requireAuth: false},
   component: (resolve) => require(['../components/login/login.vue'], resolve)
  },
  {
    path: '/',
    redirect: '/layout'
  },
  {
    path: '/layout',
    component: (resolve) => require(['../layout.vue'], resolve),
    children: [
      {
        path: 'index', 
        meta: {
          type: '1',    //控制是否顯示隱藏 1顯示,2隱藏
          code: 00010001, // 后面需要控制路由高亮
          title: '首頁',  // 菜單名稱
          permissonList: [] // 權(quán)限列表
        }
        component: (resolve) => require(['@/components/index/index.vue'], resolve)
      },
      {
      ...
      }   
    ]
  }]
})

根據(jù)以上結(jié)構(gòu)分析,其實(shí)真正需要?jiǎng)討B(tài)配置的路由其實(shí)是/layout下面的children部分,所以需要后端返回給我們包含所有路由的一個(gè)數(shù)組就可以了


返回的數(shù)據(jù)中rootList中是一級(jí)導(dǎo)航的列表,一級(jí)導(dǎo)航實(shí)際是沒有路由功能,只是作為切換二級(jí)菜單的觸發(fā)器,subList才是我們真正需要的路由信息。

3、拿到權(quán)限路由信息后,需要我們?cè)诒镜貙?duì)數(shù)據(jù)進(jìn)行處理組裝成我們需要的數(shù)據(jù):

// 登錄
   login () {
    let params = {
     account: this.loginForm.username,
     password: encrypt(this.loginForm.password)
    }
    this.loading = true
    this.$http.post(this.$bumng + '/login', this.$HP(params))
     .then((res) => {
      this.loging = false
      console.info('菜單列表:', res)
      if (res.resultCode === this.$state_ok) {
       // 合并一級(jí)菜單和二級(jí)菜單,便于顯示
       let menus = handleMenu.mergeSubInRoot(res.rootList, res.subList)
       // 本地化處理好的菜單列表
       this.saveRes({label: 'menuList', value: menus})
       // 根據(jù)subList處理路由
       let routes = handleMenu.mergeRoutes(res.subList)
       // 本地化subList,便于在刷新頁面的時(shí)候重新配置路由
       this.saveRes({label: 'subList', value: res.subList})
       // 防止重復(fù)配置相同路由
       if (this.$router.options.routes.length <= 1) {
        this.$router.addRoutes(routes)
        // this.$router不是響應(yīng)式的,所以手動(dòng)將路由元注入路由對(duì)象
        this.$router.options.routes.push(routes)
       }
       this.$router.replace('/layout/index')
      }
     })
     .catch((err) => {
      this.loging = false
      console.error('錯(cuò)誤:', err)
     })
   },

處理菜單列表和subList的方法:mergeSubInRoot 和 mergeRoutes

const routes = [
 {
  path: '/',
  redirect: '/layout'
 },
 {
  path: '/layout',
  component: (resolve) => require(['../layout.vue'], resolve),
  children: []
 }
]
export default {
 /**
  * 合并主菜單和子菜單
  * @param: rootList [Array] 主菜單列表
  * @param: subList [Array] 子菜單
  * */
 mergeSubInRoot (roots, subs) {
  if (roots && subs) {
   for (let i = 0; i < roots.length; i++) {
    let rootCode = roots[i].code
    roots[i].children = []
    for (let j = 0; j < subs.length; j++) {
     if (rootCode === subs[j].code.substring(0, 4)) {
      roots[i].children.push(subs[j])
     }
    }
   }
  }
  return roots
 },
 /**
  * 合并遠(yuǎn)程路由到本地路由
  * @param: subList [Array] 遠(yuǎn)程路由列表
  * @param: routes [Array] 本地路由列表
  * */
 mergeRoutes (subs) {
  if (subs) {
   for (let i = 0; i < subs.length; i++) {
    let temp = {
     path: subs[i].actUrl,
     name: subs[i].actUrl,
     component: (resolve) => require([`@/components/${subs[i].component}.vue`], resolve),
     meta: {
      type: subs[i].type,
      code: subs[i].code,
      title: subs[i].name,
      permissionList: subs[i].permissionList
     }
    }
    routes[1].children.push(temp)
   }
  }
  return routes
 }
}

至此我們已經(jīng)將權(quán)限路由成功配置進(jìn)本地路由了,我的系統(tǒng)登錄進(jìn)入如下

后續(xù)優(yōu)化

1、菜單列表的顯示以及二級(jí)導(dǎo)航切換:

<template>
  <div class="mainMenu">
   <el-menu
    class="menubar"
    mode="horizontal"
    :default-active="activeCode"
    background-color="#545c64"
    text-color="#fff"
    active-text-color="#ffd04b">
    <el-menu-item :index="item.code | splitCode" v-for="item in menuList" :key="item.code" @click="switchSubMenu(item)" v-if="item.code !== '0008'">
     <i :class="`iconfont icon-${item.imgUrl}`"></i>
     <span slot="title">{{item.name}}</span>
    </el-menu-item>
   </el-menu>
  </div>
</template>

<script type="text/ecmascript-6">
 import {mapState, mapMutations} from 'vuex'
 export default {
  name: 'menu',
  data () {
   return {
    msg: 'Welcome to Your Vue.js App'
   }
  },
  computed: {
   ...mapState(['menuList']),
   activeCode () {
     // 通過code保證在切換字路由的情況下一級(jí)路由也是高亮顯示
    return this.$route.meta.code.substring(0, 4)
   }
  },
  methods: {
   ...mapMutations(['saveRes']),
   // 切換二級(jí)路由
   switchSubMenu (route) {
    console.info('路由:', route)
    if (route.actUrl !== 'index') {
     // 用currentSubMenu控制二級(jí)路由數(shù)據(jù) 
     this.saveRes({label: 'currentSubMenu', value: route.children})
     this.$router.push(`/layout/${route.children[0].actUrl}`)
    } else {
     // 不存在二級(jí)路由隱藏二級(jí) 
     this.saveRes({label: 'currentSubMenu', value: ''})
     this.$router.push(`/layout/${route.actUrl}`)
    }
   }
  },
  filters: {
   splitCode (code) {
    return code.substring(0, 4)
   }
  }
 }
</script>

2、防止刷新路由丟失;由于在刷新的時(shí)候單頁應(yīng)用會(huì)重新初始化,這時(shí)候所有配置的路由都會(huì)丟失,一朝回到解放前,只有本地配置的路由能夠跳轉(zhuǎn)。這時(shí)候我們可以在app.vue(ps:不論在哪里進(jìn)行刷新,app.vue都會(huì)執(zhí)行)中執(zhí)行如下代碼:

<script>
 import {decrypt} from '@/libs/AES'
 import handleMenu from '@/router/handleMenu'
 export default {
  name: 'app',
  created () {
   // 當(dāng)this.$router.options.routes的長度為1,且本地緩存存在菜單列表的時(shí)候才重新配置路由
   if (this.$router.options.routes.length <= 1 && sessionStorage.getItem('subList')) {
    let subList = JSON.parse(decrypt(sessionStorage.getItem('subList')))
    let routes = handleMenu.mergeRoutes(subList)
    this.$router.addRoutes(routes)
    // this.$router不是響應(yīng)式的,所以手動(dòng)將路由元注入路由對(duì)象
    this.$router.options.routes.push(routes)
   }
  }
 }
</script>

這樣即使刷新,也會(huì)重新配置路由了。

3、關(guān)于頁面按鈕級(jí)別控制,可以自定義一個(gè)指令,去做這件事情。因?yàn)槲覀円呀?jīng)權(quán)限列表放入了相應(yīng)路由的meta對(duì)象中,所以我們可以很方便的在每個(gè)頁面回去到當(dāng)前用戶在當(dāng)前頁面所擁有的權(quán)限

參考官方文檔自定義指令

結(jié)語

打完收工,得虧vue-router2中添加了addRoutes的方法,不然

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決vue路由組件vue-router實(shí)例被復(fù)用問題

    解決vue路由組件vue-router實(shí)例被復(fù)用問題

    這篇文章介紹了解決vue路由組件vue-router實(shí)例被復(fù)用的問題,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 如何將百度地圖包裝成Vue的組件的方法步驟

    如何將百度地圖包裝成Vue的組件的方法步驟

    這篇文章主要介紹了如何將百度地圖包裝成Vue的組件的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • 從零開始實(shí)現(xiàn)Vue簡(jiǎn)單的Toast插件

    從零開始實(shí)現(xiàn)Vue簡(jiǎn)單的Toast插件

    這篇文章主要給大家介紹了如何從零開始實(shí)現(xiàn)Vue簡(jiǎn)單的Toast插件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 使用vue-draggable-plus實(shí)現(xiàn)拖拽排序

    使用vue-draggable-plus實(shí)現(xiàn)拖拽排序

    最近遇到一個(gè)需求,在 Vue3 的一個(gè) H5 頁面當(dāng)中點(diǎn)擊拖拽圖標(biāo)上下拖動(dòng) tab 子項(xiàng),然后點(diǎn)擊保存可以保存最新的 tab 項(xiàng)順序,同事說可以用 vue-draggable-plus 這個(gè)庫來實(shí)現(xiàn)拖拽,所以本文給大家介紹了如何使用vue-draggable-plus實(shí)現(xiàn)拖拽排序,需要的朋友可以參考下
    2024-01-01
  • 實(shí)現(xiàn)一個(gè)Vue自定義指令懶加載的方法示例

    實(shí)現(xiàn)一個(gè)Vue自定義指令懶加載的方法示例

    這篇文章主要介紹了實(shí)現(xiàn)一個(gè)Vue自定義指令懶加載的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 詳解如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vuex

    詳解如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vuex

    本篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 vuex,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-02-02
  • 如何換個(gè)角度使用VUE過濾器詳解

    如何換個(gè)角度使用VUE過濾器詳解

    這篇文章主要給大家介紹了如何換個(gè)角度使用VUE過濾器的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用VUE具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • vue自定義底部導(dǎo)航欄Tabbar的實(shí)現(xiàn)代碼

    vue自定義底部導(dǎo)航欄Tabbar的實(shí)現(xiàn)代碼

    這篇文章主要介紹了vue自定義底部導(dǎo)航欄Tabbar的實(shí)現(xiàn)代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • Vue之常用的內(nèi)置指令詳解

    Vue之常用的內(nèi)置指令詳解

    這篇文章主要為大家介紹了Vue之常用的內(nèi)置指令,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • Vue組件之間的通信方式詳細(xì)講解

    Vue組件之間的通信方式詳細(xì)講解

    對(duì)于vue來說,組件之間的消息傳遞是非常重要的,用vue可以是要組件復(fù)用的,而組件實(shí)例的作用域是相互獨(dú)立,這意味著不同組件之間的數(shù)據(jù)無法互相引用,一般來說,組件之間可以有幾種關(guān)系,下面是我對(duì)組件之間消息傳遞的常用方式的總結(jié)
    2022-08-08

最新評(píng)論