欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue-router+vuex addRoutes實(shí)現(xiàn)路由動(dòng)態(tài)加載及菜單動(dòng)態(tài)加載

 更新時(shí)間:2017年09月28日 10:44:30   作者:BeArchitect  
本篇文章主要介紹了vue-router+vuex addRoutes實(shí)現(xiàn)路由動(dòng)態(tài)加載及菜單動(dòng)態(tài)加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

此案例主要實(shí)現(xiàn)了一個(gè)功能是,在vue實(shí)例首次運(yùn)行時(shí),在加載了login和404兩個(gè)路由規(guī)則,登錄成功后,根據(jù)登錄用戶(hù)角色權(quán)限獲取該角色相應(yīng)菜單權(quán)限,生成新的路由規(guī)則添加進(jìn)去。

做過(guò)后臺(tái)管理系統(tǒng)都一定做過(guò)這個(gè)功能,在對(duì)菜單權(quán)限進(jìn)行粗粒度權(quán)限控制的時(shí)候,通過(guò)角色獲取菜單后,異步生成菜單,所以一開(kāi)始拿到需求的時(shí)候,我也以為這和平常的沒(méi)什么不同,不過(guò)做起來(lái)就發(fā)現(xiàn)了很多問(wèn)題,

1.vue-router的實(shí)例,在new vue實(shí)例的時(shí)候,就加載了,且必須加載,這個(gè)時(shí)候,登錄路由一定要加載,可是這個(gè)時(shí)候沒(méi)有登錄,無(wú)法確定權(quán)限
2.路由規(guī)則與菜單的同步

解決思路演化,菜單和路由同步,肯定是采用了vuex,一開(kāi)始的思路的是,在一開(kāi)始,就把所有的路由規(guī)則加載,然后在登錄的時(shí)候,取得權(quán)限路由,對(duì)比兩個(gè)路由,通過(guò)修改修改一個(gè)權(quán)限字段來(lái)隱藏菜單,如果在后臺(tái)頁(yè)面添加了新菜單規(guī)則,路由是按模塊加載的不同的文件,這時(shí)對(duì)路由的文件進(jìn)行新的讀寫(xiě),雖然可以解決問(wèn)題,但是如果手動(dòng)在瀏覽器地址上路由,依然可以訪(fǎng)問(wèn),所以在路由的全局鉤子上還要做攔截。

這個(gè)解決方案雖然解決,但是顯的比較復(fù)雜,于是就想需找新的方法,重新瀏覽官方api,發(fā)現(xiàn)在2.2.0以后,官方新增了api,addRoutes,專(zhuān)門(mén)針對(duì)服務(wù)端渲染路由,那么這下問(wèn)題就比較簡(jiǎn)單了,下面列出實(shí)現(xiàn)代碼。以下代碼不能直接復(fù)用,需要根據(jù)實(shí)際情況修改,只是提供思路

app.js

let permission = JSON.parse(window.sessionStorage.getItem('permission')) 
if (permission) { 
 store.commit(ADD_MENU, permission) 
 router.addRoutes(store.state.menu.items) 
} 
router.beforeEach((route, redirect, next) => { 
 if (state.app.device.isMobile && state.app.sidebar.opened) { 
  store.commit(TOGGLE_SIDEBAR, false) 
 } 
 if (route.path === '/login') { 
  window.sessionStorage.removeItem('user') 
  window.sessionStorage.removeItem('permission') 
  store.commit(ADD_MENU, []) 
 } 
 let user = JSON.parse(window.sessionStorage.getItem('user')) 
 if (!user && route.path !== '/login') { 
  next({ path: '/login' }) 
 } else { 
  if (route.name) { 
   next() 
  } else { 
   next({ path: '/nofound' }) 
  } 
 } 
}) 

登錄的組件login.vue

<template> 
 <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-position="left" label-width="0px" 
      class="demo-ruleForm login-container"> 
  <h3 class="title">系統(tǒng)登錄</h3> 
  <el-form-item prop="account"> 
   <el-input type="text" v-model="ruleForm2.account" auto-complete="off" placeholder="賬號(hào)"></el-input> 
  </el-form-item> 
  <el-form-item prop="checkPass"> 
   <el-input type="password" v-model="ruleForm2.checkPass" auto-complete="off" placeholder="密碼"></el-input> 
  </el-form-item> 
  <el-checkbox v-model="checked" checked class="remember">記住密碼</el-checkbox> 
  <el-form-item style="width:100%;"> 
   <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit2" :loading="logining">登錄 
   </el-button> 
   <!--<el-button @click.native.prevent="handleReset2">重置</el-button>--> 
  </el-form-item> 
 </el-form> 
</template> 
 
<script> 
 import NProgress from 'nprogress' 
 import { mapActions, mapGetters } from 'vuex' 
 export default { 
  data () { 
   return { 
    logining: false, 
    ruleForm2: { 
     account: 'admin', 
     checkPass: '123456' 
    }, 
    rules2: { 
     account: [ 
      {required: true, message: '請(qǐng)輸入賬號(hào)', trigger: 'blur'} 
      // { validator: validaePass } 
     ], 
     checkPass: [ 
      {required: true, message: '請(qǐng)輸入密碼', trigger: 'blur'} 
      // { validator: validaePass2 } 
     ] 
    }, 
    checked: true 
   } 
  }, 
  computed: { 
   ...mapGetters([ 
    'menuitems', 
    'isLoadRoutes' 
    // ... 
   ]) 
  }, 
  methods: { 
   handleReset2 () { 
    this.$refs.ruleForm2.resetFields() 
   }, 
   handleSubmit2 (ev) { 
    this.$refs.ruleForm2.validate((valid) => { 
     if (valid) { 
      this.logining = true 
      NProgress.start() 
      let loginParams = {loginName: this.ruleForm2.account, password: this.ruleForm2.checkPass} 
      this.$http.post('/api/privilege/user/login', loginParams).then(resp => { 
       this.logining = false 
       NProgress.done() 
       let {message, data} = resp.data 
 
       if (message === 'fail') { 
        this.$notify({ 
         title: '錯(cuò)誤', 
         message: message, 
         type: 'error' 
        }) 
       } else { 
        window.sessionStorage.setItem('user', JSON.stringify(data.user)) 
        window.sessionStorage.setItem('permission', JSON.stringify(data.permission)) 
        this.addMenu(data.permission) 
        if (!this.isLoadRoutes) { 
         this.$router.addRoutes(this.menuitems) 
         this.loadRoutes() 
        } 
        this.$router.push('/system/office') 
       } 
      }) 
     } else { 
      console.log('error submit!!') 
      return false 
     } 
    }) 
   }, 
 
   ...mapActions([ 
    'addMenu', 
    'loadRoutes' 
   ]) 
  } 
 } 
 
</script> 
 
<style lang="scss" scoped> 
 .login-container { 
  /*box-shadow: 0 0px 8px 0 rgba(0, 0, 0, 0.06), 0 1px 0px 0 rgba(0, 0, 0, 0.02);*/ 
  -webkit-border-radius: 5px; 
  border-radius: 5px; 
  -moz-border-radius: 5px; 
  background-clip: padding-box; 
  margin-bottom: 20px; 
  background-color: #F9FAFC; 
  margin: 180px auto; 
  border: 2px solid #8492A6; 
  width: 350px; 
  padding: 35px 35px 15px 35px; 
 
 .title { 
  margin: 0px auto 40px auto; 
  text-align: center; 
  color: #505458; 
 } 
 
 .remember { 
  margin: 0px 0px 35px 0px; 
 } 
 
 } 
</style> 

關(guān)鍵點(diǎn)解釋

computed: { 
   ...mapGetters([ 
    'menuitems', 
    'isLoadRoutes' 
    // ... 
   ]) 
  }, 

這里是從vuex取得兩個(gè)對(duì)象,menuitems是菜單對(duì)象,isLoadRoutes是用來(lái)判斷是否是第一次登錄,用來(lái)排除重復(fù)加載路由規(guī)則

...mapActions([ 
    'addMenu', 
    'loadRoutes' 
   ]) 

這里是從vuex取得兩個(gè)方法,一個(gè)是添加菜單,一個(gè)更改loadRoutes的值

this.$router.addRoutes(this.menuitems) 

這是關(guān)鍵api,動(dòng)態(tài)的向router實(shí)例中添加路由規(guī)則

menu模塊的state與mutations

const state = { 
 items: [ 
 ], 
 isLoadRoutes: false 
} 
 
const mutations = { 
 [types.EXPAND_MENU] (state, menuItem) { 
  if (menuItem.index > -1) { 
   if (state.items[menuItem.index] && state.items[menuItem.index].meta) { 
    state.items[menuItem.index].meta.expanded = menuItem.expanded 
   } 
  } else if (menuItem.item && 'expanded' in menuItem.item.meta) { 
   menuItem.item.meta.expanded = menuItem.expanded 
  } 
 }, 
 [types.ADD_MENU] (state, menuItems) { 
  if (menuItems.length === 0) { 
   state.items = [] 
  } else { 
   generateMenuItems(state.items, menuItems) 
  } 
 }, 
 [types.LOAD_ROUTES] (state) { 
  state.isLoadRoutes = !state.isLoadRoutes 
 } 
} 

路由配置文件router.js

import Vue from 'vue' 
import Router from 'vue-router' 
import menuModule from 'vuex-store/modules/menu' 
Vue.use(Router) 
 
export default new Router({ 
 mode: 'hash', // Demo is living in GitHub.io, so required! 
 linkActiveClass: 'is-active', 
 scrollBehavior: () => ({ y: 0 }), 
 routes: [ 
  { 
   path: '/login', 
   component: require('../Login.vue'), 
   meta: { 
    expanded: false, 
    show: false 
   }, 
   name: 'Login' 
  }, 
  { 
   path: '/', 
   component: require('../views/Home.vue'), 
   meta: { 
    expanded: false, 
    show: false 
   }, 
   children: [ 
    { path: '/nofound', component: require('../404.vue'), name: 'NOFOUND', meta: {show: false} } 
   ] 
  }, 
  ...generateRoutesFromMenu(menuModule.state.items) 
 ] 
}) 
 
// Menu should have 2 levels. 
function generateRoutesFromMenu (menu = [], routes = []) { 
 for (let i = 0, l = menu.length; i < l; i++) { 
  let item = menu[i] 
  if (item.path) { 
   routes.push(item) 
  } 
 } 
 return routes 
} 

vuex

import Vue from 'vue' 
import Vuex from 'vuex' 
import * as actions from './actions' 
import * as getters from './getters' 
 
import menu from './modules/menu' 
 
Vue.use(Vuex) 
 
const store = new Vuex.Store({ 
 strict: true, // process.env.NODE_ENV !== 'development', 
 actions, 
 getters, 
 modules: { 
  menu 
 }, 
 mutations: { 
 } 
}) 
 
export default store 

actions

export const addMenu = ({ commit }, menuItems) => { 
 if (menuItems.length > 0) { 
  commit(types.ADD_MENU, menuItems) 
 } 
} 
 
export const loadRoutes = ({ commit }) => { 
 commit(types.LOAD_ROUTES) 
} 

getters

const menuitems = state => state.menu.items 
const isLoadRoutes = state => state.menu.isLoadRoutes 
export { 
 menuitems, 
 isLoadRoutes 
} 

mutations_type.js

export const ADD_MENU = 'ADD_MENU' 
 
export const LOAD_ROUTES = 'LOAD_ROUTES' 

因?yàn)樯厦娴拇a不能直接運(yùn)行,再次梳理一下思路,

1.創(chuàng)建vue實(shí)例的時(shí)候,將vuex和vue-router加載,這個(gè)時(shí)候,vue-router只有登錄規(guī)則和404規(guī)則

2.vuex中state管理的狀態(tài)對(duì)象有,菜單對(duì)象menuitems,是否加載過(guò)路由loadRoutes ,并提供相應(yīng)的getters與actions當(dāng)然還有一些其他的,這里沒(méi)有列舉

3.然后在登錄組件中,登錄成功后,將服務(wù)端傳回來(lái)之后,調(diào)用actions更改state.menuitems,并且中間有格式化的過(guò)程,這個(gè)過(guò)程的代碼沒(méi)有貼出來(lái),主要是由于不同的表涉和服務(wù)端返回的數(shù)據(jù)不一樣,,

4.然后調(diào)用addRoutes和actions更改已經(jīng)加載過(guò)路由的方法

5.然后為了防止用戶(hù)直接手動(dòng)按f5刷新頁(yè)面,這個(gè)時(shí)候會(huì)重新構(gòu)建vue實(shí)例,而又沒(méi)有重新登錄,所以vuex里面的東西會(huì)清空,所以將登錄后的數(shù)據(jù)存放在sessionStroage中,在刷新頁(yè)面,重新構(gòu)建vue實(shí)例的時(shí)候,會(huì)有判斷

6.之后會(huì)渲染側(cè)邊欄組件,列出菜單,數(shù)據(jù)就可以根據(jù)state.menuitems來(lái)就可以了,我這里沒(méi)有貼我的,實(shí)際根據(jù)自己的需求來(lái)

后面有時(shí)間會(huì)在github上上傳完整代碼。

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

相關(guān)文章

  • 一文詳解Vue3中簡(jiǎn)單diff算法的實(shí)現(xiàn)

    一文詳解Vue3中簡(jiǎn)單diff算法的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹Vue3中簡(jiǎn)單diff算法的實(shí)現(xiàn)與使用,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以了解一下
    2022-09-09
  • vue?請(qǐng)求后端數(shù)據(jù)的示例代碼

    vue?請(qǐng)求后端數(shù)據(jù)的示例代碼

    在vue中,我們?nèi)绾瓮ㄟ^(guò)請(qǐng)求接口來(lái)訪(fǎng)問(wèn)后端的數(shù)據(jù)呢?在這里簡(jiǎn)單總結(jié)了一個(gè)小示例,對(duì)vue請(qǐng)求后端數(shù)據(jù)實(shí)例代碼感興趣的朋友一起看看吧
    2022-09-09
  • Vue手動(dòng)控制點(diǎn)擊事件Click觸發(fā)方式

    Vue手動(dòng)控制點(diǎn)擊事件Click觸發(fā)方式

    這篇文章主要介紹了Vue手動(dòng)控制點(diǎn)擊事件Click觸發(fā)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 用vue2.0實(shí)現(xiàn)點(diǎn)擊選中active其他選項(xiàng)互斥的效果

    用vue2.0實(shí)現(xiàn)點(diǎn)擊選中active其他選項(xiàng)互斥的效果

    這篇文章主要介紹了用vue2.0實(shí)現(xiàn)點(diǎn)擊選中active其他選項(xiàng)互斥的效果,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Vue?Steam同款登錄驗(yàn)證數(shù)字輸入框功能

    Vue?Steam同款登錄驗(yàn)證數(shù)字輸入框功能

    這篇文章主要介紹了Vue?Steam同款登錄驗(yàn)證數(shù)字輸入框功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-03-03
  • 在VUE3中禁止網(wǎng)頁(yè)返回到上一頁(yè)的方法

    在VUE3中禁止網(wǎng)頁(yè)返回到上一頁(yè)的方法

    這篇文章主要介紹了在VUE3中如何禁止網(wǎng)頁(yè)返回到上一頁(yè),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • vue+echarts繪制省份地圖并添加自定義標(biāo)注方式

    vue+echarts繪制省份地圖并添加自定義標(biāo)注方式

    這篇文章主要介紹了vue+echarts繪制省份地圖并添加自定義標(biāo)注方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 詳解在vue使用weixin-js-sdk常見(jiàn)使用方法

    詳解在vue使用weixin-js-sdk常見(jiàn)使用方法

    這篇文章主要介紹了 詳解在vue使用weixin-js-sdk常見(jiàn)使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • VUE2響應(yīng)式原理使用Object.defineProperty缺點(diǎn)

    VUE2響應(yīng)式原理使用Object.defineProperty缺點(diǎn)

    這篇文章主要為大家介紹了VUE2響應(yīng)式原理使用Object.defineProperty缺點(diǎn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Vuex給state中的對(duì)象新添加屬性遇到的問(wèn)題及解決

    Vuex給state中的對(duì)象新添加屬性遇到的問(wèn)題及解決

    這篇文章主要介紹了Vuex給state中的對(duì)象新添加屬性遇到的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評(píng)論