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

基于vue,vue-router, vuex及addRoutes進行權(quán)限控制問題

 更新時間:2018年05月02日 16:56:13   作者:Runlin  
這篇文章主要介紹了基于vue,vue-router, vuex及addRoutes進行權(quán)限控制問題,需要的朋友可以參考下

基于vuex, vue-router,vuex的權(quán)限控制教程,完整代碼地址見 https://github.com/linrunzheng/vue-permission-control

接下來讓我們模擬一個普通用戶打開網(wǎng)站的過程,一步一步的走完整個流程。

首先從打開本地的服務localhost:8080開始,我們知道打開后會進入login頁面,那么判斷的依據(jù)是什么。

首先是token。

沒有登陸的用戶是獲取不到token的,而登陸后的角色我們會將token存到local或者seesionStorage 因此,根據(jù)當前有沒有token即可知道是否登陸。

為了存取token并且方便我們操作,可以配和vuex實現(xiàn)

/* state.js */
export default {
 get UserToken() {
 return localStorage.getItem('token')
 },
 set UserToken(value) {
 localStorage.setItem('token', value)
 }
}
/* mutation.js */
export default {
 LOGIN_IN(state, token) {
 state.UserToken = token
 },
 LOGIN_OUT(state) {
 state.UserToken = ''
 }
}

攔截的判斷

沒有token進入需要權(quán)限的頁面:redirect到login頁面

由于我們路由是動態(tài)掛載的,包括 ' ' 和404,所以當匹配不到路由時,也重定向到login

router.beforeEach((to, from, next) => {
 if (!store.state.UserToken) {
 if (
 to.matched.length > 0 &&
 !to.matched.some(record => record.meta.requiresAuth)
 ) {
 next()
 } else {
 next({ path: '/login' })
 }
 } 
})

好了,此時用戶打開localhost:8080,默認匹配的是''路徑,此時我們并沒有掛載路由,也沒有token,所以來到了login。

輸入用戶名密碼后,有token了,通過store觸發(fā)* commit('LOGIN_IN')* 來設置token。

但是還是沒有路由,目前最開始只有l(wèi)ogin路由

/* 初始路由 */
export default new Router({
 routes: [
 {
 path: '/login',
 component: Login
 }
 ]
})
/* 準備動態(tài)添加的路由 */
export const DynamicRoutes = [
 {
 path: '',
 component: Layout,
 name: 'container',
 redirect: 'home',
 meta: {
 requiresAuth: true,
 name: '首頁'
 },
 children: [
 {
 path: 'home',
 component: Home,
 name: 'home',
 meta: {
  name: '首頁'
 }
 }
 ]
 },
 {
 path: '/403',
 component: Forbidden
 },
 {
 path: '*',
 component: NotFound
 }
]

我們要根據(jù)當前用戶的token去后臺獲取權(quán)限。

由于權(quán)限這塊邏輯還挺多,所以在vuex添加了一個permission模塊來處理權(quán)限。

為了判斷是已有路由列表,需要在vuex的permission模塊存一個state狀態(tài)permissionList用來判斷,假如permissionList不為null,即已經(jīng)有路由,如果不存在,就需要我們干活了。

router.beforeEach((to, from, next) => {
 if (!store.state.UserToken) {
 ...
 } else {
 /* 現(xiàn)在有token了 */
 if (!store.state.permission.permissionList) {
 /* 如果沒有permissionList,真正的工作開始了 */
 store.dispatch('permission/FETCH_PERMISSION').then(() => {
 next({ path: to.path })
 })
 } else {
 if (to.path !== '/login') {
 next()
 } else {
 next(from.fullPath)
 }
 }
 }
})

來看一下 store.dispatch('permission/FETCH_PERMISSION') 都干了什么

actions: {
 async FETCH_PERMISSION({ commit, state }) {
 /* 獲取后臺給的權(quán)限數(shù)組 */
 let permissionList = await fetchPermission()
 /* 根據(jù)后臺權(quán)限跟我們定義好的權(quán)限對比,篩選出對應的路由并加入到path=''的children */
 let routes = recursionRouter(permissionList, dynamicRouter)
 let MainContainer = DynamicRoutes.find(v => v.path === '')
 let children = MainContainer.children
 children.push(...routes)
 /* 生成左側(cè)導航菜單 */
 commit('SET_MENU', children)
 setDefaultRoute([MainContainer])
 /* 初始路由 */
 let initialRoutes = router.options.routes
 /* 動態(tài)添加路由 */
 router.addRoutes(DynamicRoutes)
 /* 完整的路由表 */
 commit('SET_PERMISSION', [...initialRoutes, ...DynamicRoutes])
 }
}

首先,await fetchPermission()獲取后臺給的權(quán)限數(shù)組,格式大概如下

{
 "code": 0,
 "message": "獲取權(quán)限成功",
 "data": [
 {
 "name": "訂單管理",
 "children": [
 {
  "name": "訂單列表"
 },
 {
  "name": "生產(chǎn)管理",
  "children": [
  {
  "name": "生產(chǎn)列表"
  }  
  ]
 },
 {
  "name": "退貨管理"
 }
 ]
 }
 ]
}

其次根據(jù)我們寫好的路由數(shù)組,進行對比,過濾得到我們要的路由

/* 這里是我們寫好的需要權(quán)限判斷的路由 */
const dynamicRoutes = [
 {
 path: '/order',
 component: Order,
 name: 'order-manage',
 meta: {
 name: '訂單管理'
 },
 children: [
 {
 path: 'list',
 name: 'order-list',
 component: OrderList,
 meta: {
  name: '訂單列表'
 }
 },
 {
 path: 'product',
 name: 'product-manage',
 component: ProductManage,
 meta: {
  name: '生產(chǎn)管理'
 },
 children: [
  {
  path: 'list',
  name: 'product-list',
  component: ProductionList,
  meta: {
  name: '生產(chǎn)列表'
  }
  },
  {
  path: 'review',
  name: 'review-manage',
  component: ReviewManage,
  meta: {
  name: '審核管理'
  }
  }
 ]
 },
 {
 path: 'returnGoods',
 name: 'return-goods',
 component: ReturnGoods,
 meta: {
  name: '退貨管理'
 }
 }
 ]
 }
]
export default dynamicRoutes

為了對比,我寫好了一個遞歸函數(shù),用name和meta.name進行對比 ,根據(jù)這個函數(shù)就可以得到我們想要的結(jié)果

/**
 *
 * @param {Array} userRouter 后臺返回的用戶權(quán)限json
 * @param {Array} allRouter 前端配置好的所有動態(tài)路由的集合
 * @return {Array} realRoutes 過濾后的路由
 */
export function recursionRouter(userRouter = [], allRouter = []) {
 var realRoutes = []
 allRouter.forEach((v, i) => {
 userRouter.forEach((item, index) => {
 if (item.name === v.meta.name) {
 if (item.children && item.children.length > 0) {
  v.children = recursionRouter(item.children, v.children)
 }
 realRoutes.push(v)
 }
 })
 })
 return realRoutes
}

得到過濾后的數(shù)組后,加入到path為''的children下面

{
 path: '',
 component: Layout,
 name: 'container',
 redirect: 'home',
 meta: {
 requiresAuth: true,
 name: '首頁'
 },
 children: [
 {
 path: 'home',
 component: Home,
 name: 'home',
 meta: {
  name: '首頁'
 }
 },
 <!-- 將上面得到的東西加入到這里 -->
 ...
 ]
 }

這個時候,path為''的children就是我們左側(cè)的導航菜單了,存到state的sidebarMenu待用。加入到children后,這時DynamicRoutes就可以加入到路由了。

/* 動態(tài)添加路由 */
router.addRoutes(DynamicRoutes)
 /* 初始路由 */
let initialRoutes = router.options.routes
/* 合并起來,就是完整的路由了 */
commit('SET_PERMISSION', [...initialRoutes, ...DynamicRoutes])

路由添加完了,也就是action操作完畢了,即可在action.then里面調(diào)用 next({ path: to.path })進去路由,這里要注意, next里面要傳參數(shù)即要進入的頁面的路由信息,因為next傳參數(shù)后,當前要進入的路由會被廢止,轉(zhuǎn)而進入?yún)?shù)對應的路由,雖然是同一個路由,這么做主要是為了確保addRoutes生效了。

進入路由后,要開始生成左側(cè)菜單,之前我們已經(jīng)存到sidebarMenu了,現(xiàn)在需要做的只是遞歸生成菜單而已,雖然用了element的導航菜單,但是為了遞歸路由,還需要自己封裝一下。這里核心的地方是組件的name,在組件里面有children的地方,又再次使用自己,從而遍歷整個tree結(jié)構(gòu)的路由。

<template>
 <div class="menu-container">
 <template v-for="v in menuList">
 <el-submenu :index="v.name" v-if="v.children&&v.children.length>0" :key="v.name">
 <template slot="title">
  <i class="iconfont icon-home"></i>
  <span>{{v.meta.name}}</span>
 </template>
 <el-menu-item-group>
  <my-nav :menuList="v.children"></my-nav>
 </el-menu-item-group>
 </el-submenu>
 <el-menu-item :key="v.name" :index="v.name" @click="gotoRoute(v.name)" v-else>
 <i class="iconfont icon-home"></i>
 <span slot="title">{{v.meta.name}}</span>
 </el-menu-item>
 </template>
 </div>
</template>
<script>
export default {
 name: 'my-nav',
 props: {
 menuList: {
 type: Array,
 default: function() {
 return []
 }
 }
 },
 methods: {
 gotoRoute(name) {
 this.$router.push({ name })
 }
 }
}
</script>

刷新頁面后,根據(jù)我們router.beforeEach的判斷,有token但是沒permissionList,我們是會重新觸發(fā)action去獲取路由的,所以無需擔心。但是導航菜單active效果會不見。不過我們已經(jīng)把el-menu-item的key設置為路由的name,那么我們只要在刷新后,在afterEach把當前路由的name賦值給el-menu default-active即可。同理,在afterEach階段獲取所有matched的路由,即可實現(xiàn)面包屑導航。

if (!store.state.permission.permissionList) {
 store.dispatch('permission/FETCH_PERMISSION').then(() => {
 next({ path: to.path })
 })
} 
...
router.afterEach((to, from, next) => {
 var routerList = to.matched
 store.commit('setCrumbList', routerList)
 store.commit('permission/SET_CURRENT_MENU', to.name)
})

退出登陸后,需要刷新頁面,因為我們是通過addRoutes添加的,router沒有deleteRoutes這個api,所以清除token,清除permissionList等信息,刷新頁面是最保險的。

最后還有一點,每次請求得帶上token, 可以對axios封裝一下來處理

var instance = axios.create({
 timeout: 30000,
 baseURL
})
// 添加請求攔截器
instance.interceptors.request.use(
 function(config) {
 // 請求頭添加token
 if (store.state.UserToken) {
 config.headers.Authorization = store.state.UserToken
 }
 return config
 },
 function(error) {
 return Promise.reject(error)
 }
)
/* axios請求二次封裝 */
instance.get = function(url, data, options) {
 return new Promise((resolve, reject) => {
 axios
 .get(url, data, options)
 .then(
 res => {
  var response = res.data
  if (response.code === 0) {
  resolve(response.data)
  } else {
  Message.warning(response.message)
  /* reject(response.message) */
  }
 },
 error => {
  if (error.response.status === 401) {
  Message.warning({
  message: '登陸超時,請重新登錄'
  })
  store.commit('LOGIN_OUT')
  window.location.reload()
  } else {
  Message.error({
  message: '系統(tǒng)異常'
  })
  }
  reject(error)
 }
 )
 .catch(e => {
 console.log(e)
 })
 })
}
export default instance

總結(jié)

以上所述是小編給大家介紹的基于vue,vue-router, vuex及addRoutes進行權(quán)限控制問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • vue項目設置打包后的靜態(tài)文件訪問路徑

    vue項目設置打包后的靜態(tài)文件訪問路徑

    這篇文章主要介紹了vue項目設置打包后的靜態(tài)文件訪問路徑,vue項目的最終項目文件需要經(jīng)過打包輸出,靜態(tài)文件的訪問路徑需要在vue.config.js文件中設置,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • 在vue中如何引入外部less文件

    在vue中如何引入外部less文件

    這篇文章主要介紹了在vue中如何引入外部less文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue相關(guān)配置文件詳解及多環(huán)境配置詳細步驟

    vue相關(guān)配置文件詳解及多環(huán)境配置詳細步驟

    這篇文章主要介紹了vue相關(guān)配置文件詳解及多環(huán)境配置的教程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • vue-dplayer 視頻播放器實例代碼

    vue-dplayer 視頻播放器實例代碼

    今天小編就為大家分享一篇vue-dplayer 視頻播放器實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • VUE的history模式下除了index外其他路由404報錯解決辦法

    VUE的history模式下除了index外其他路由404報錯解決辦法

    在本篇文章里小編給大家分享的是關(guān)于VUE的history模式下除了index外其他路由404報錯解決辦法,對此有需要的朋友們可以學習下。
    2019-08-08
  • vue封裝動態(tài)表格方式詳解

    vue封裝動態(tài)表格方式詳解

    這篇文章主要為大家介紹了vue封裝動態(tài)表格方式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • vue-cli腳手架的安裝教程圖解

    vue-cli腳手架的安裝教程圖解

    vue-cli腳手架模板是基于node下的npm來完成安裝,這篇文章主要介紹了vue-cli腳手架的安裝教程圖解 ,需要的朋友可以參考下
    2018-09-09
  • 淺談Vue數(shù)據(jù)響應思路之數(shù)組

    淺談Vue數(shù)據(jù)響應思路之數(shù)組

    這篇文章主要介紹了淺談Vue數(shù)據(jù)響應思路之數(shù)組,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • Vue雙向數(shù)據(jù)綁定與響應式原理深入探究

    Vue雙向數(shù)據(jù)綁定與響應式原理深入探究

    本節(jié)介紹雙向數(shù)據(jù)綁定以及響應式的原理,回答了雙向數(shù)據(jù)綁定和數(shù)據(jù)響應式是否相同,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-08-08
  • vue通過krpano.js實現(xiàn)360全景圖的實例代碼

    vue通過krpano.js實現(xiàn)360全景圖的實例代碼

    這篇文章主要介紹了vue上通過krpano.js實現(xiàn)360全景圖,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-10-10

最新評論