日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > vue >内容正文

vue

activemenu怎么拼 vue_vue-element-admin登录逻辑,以及动态添加路由,显示侧边栏

發(fā)布時間:2023/12/15 vue 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 activemenu怎么拼 vue_vue-element-admin登录逻辑,以及动态添加路由,显示侧边栏 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這段時間在研究element-admin,感覺這個庫有許多值得學(xué)習(xí)的地方,我學(xué)習(xí)這個庫的方法是,先看它的路由,順著路由,摸清它的邏輯,有點像順藤摸瓜。

這個庫分的模塊非常清晰,適合多人合作開發(fā)項目,但是如果一個人去用這個庫開發(fā)后臺,步驟顯的有點繁瑣,特別是調(diào)用后端接口,之前一個方法就調(diào)用到了,但是用這個庫,需要先后分幾步調(diào)用。

比如說調(diào)用一個登陸接口:點擊登陸按鈕----》調(diào)用store中的方法----》調(diào)用api中對應(yīng)登陸的方法---》request.js中封裝的axios方法

4步!!!!,讓我看來確實是有點繁瑣,這個問題到后面解決,通過自己封裝的axios方法,直接調(diào)用后臺接口,目前不知道會不會遇到其它問題。好了,接下來進(jìn)入正題!!!

接下來先介紹一下,element-admin的登錄邏輯

1、先看登錄方法里寫什么:

handleLogin() {

this.$refs.loginForm.validate(valid => {

if (valid) {

this.loading = true;

//調(diào)用user模塊紅的login

console.log("點擊登陸按鈕")

this.$store.dispatch('user/login', this.loginForm).then(() => {

console.log("登錄成功");

this.$router.push({ path: this.redirect || '/' });

this.loading = false;

}).catch(() => {

this.loading = false;

})

} else {

console.log('error submit!!');

return false;

}

})

}

通過上面紅色代碼,可以看出,點擊過登錄按鈕后,調(diào)用了$store里的一個方法,名叫l(wèi)ogin

2、下面來看看$store里的這個login方法:

import { login, logout, getInfo,self} from '@/api/user'

const actions = {

// user login

login({ commit }, userInfo) {

const { username, password } = userInfo;

return new Promise((resolve, reject) => {

console.log("vuex中的請求")

login({ username: username.trim(), password: password }).then(response => {

console.log('vuex中')

console.log(response);

const { data } = response;

commit('SET_TOKEN', data.token);//存在vueX中

setToken(data.token);//存在cookie中

resolve();

}).catch(error => {

console.log(error);

reject(error);

})

})

},

咿,怎么兩個login,熟悉vuex的話應(yīng)該知道,第一個login是$store中的方法,第二個login方法是,api里的login方法,用來調(diào)用接口的

3、再來看看api中的login方法:

import request from '@/utils/request'

export function login(data) {

return request({

url: '/user/login',

method: 'post',

data

})

}

上面是api中的login方法,它調(diào)用了request.js,request.js是封裝了axios,是用來請求后臺接口的,如果這個接口請求成功了,就回到了第一步中的.then()方法中

代碼是,路由跳轉(zhuǎn)到首頁,進(jìn)入正式頁面!!!

重點來了!!!

之所以是稱之為權(quán)限,也就是必須滿足一定的條件才能夠訪問到正常頁面,那么如果不滿足呢?如果我沒有token,讓不讓我進(jìn)正常頁面呢??

肯定是不讓的,那我沒有token,該去哪?答案是還待在登錄頁,哪都去不了,那么這些處理應(yīng)該在哪寫呢?答案是,permission.js模塊

這個js在main.js引入,其實就是個路由攔截器:來看看它的代碼:

import router from './router'

import store from './store'

import { Message } from 'element-ui'

import NProgress from 'nprogress' // progress bar 一個進(jìn)度條的插件

import 'nprogress/nprogress.css' // progress bar style

import { getToken } from '@/utils/auth' // get token from cookie

import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration 是否有轉(zhuǎn)圈效果

const whiteList = ['/login'] // 沒有重定向白名單

router.beforeEach(async(to, from, next) => {

// 開始進(jìn)度條

NProgress.start()

// 設(shè)置頁面標(biāo)題

document.title = getPageTitle(to.meta.title)

// 確定用戶是否已登錄

const hasToken = getToken()

if (hasToken) {

if (to.path === '/login') {

// 如果已登錄,則重定向到主頁

next({ path: '/' })

NProgress.done()

} else {

const hasGetUserInfo = store.getters.name;

console.log(hasGetUserInfo);

if (hasGetUserInfo) {

console.log("有用戶信息");

next();

} else {

console.log("無用戶信息")

try {

// 獲得用戶信息

await store.dispatch('user/getInfo');

//實際是請求用戶信息后返回,這里是模擬數(shù)據(jù),直接從store中取

const roles=store.getters.roles;

store.dispatch('permission/GenerateRoutes', { roles }).then(() => { // 生成可訪問的路由表

router.addRoutes(store.getters.addRouters); // 動態(tài)添加可訪問路由表

router.options.routes=store.getters.routers;

next({ ...to, replace: true });// hack方法 確保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record

})

// next()

} catch (error) {

// 刪除token,進(jìn)入登錄頁面重新登錄

await store.dispatch('user/resetToken');

Message.error(error || 'Has Error');

next(`/login?redirect=${to.path}`);

NProgress.done();

}

}

}

} else {

/* has no token*/

if (whiteList.indexOf(to.path) !== -1) {

// 在免費(fèi)登錄白名單,直接去

next()

} else {

// 沒有訪問權(quán)限的其他頁面被重定向到登錄頁面。

next(`/login?redirect=${to.path}`)

NProgress.done()

}

}

})

router.afterEach(() => {

// 完成進(jìn)度條

NProgress.done()

})

一看代碼好多,不過不要怕,我來分析一下它的情況,不就是點if else嘛

從上面代碼看,每次路由跳轉(zhuǎn),都要從cookie中取token,

那么可以分兩種情況,有token和無token

有token:再看看是不是去登錄頁的,登錄頁肯定不能攔截的,如果是登錄頁就直接放行。如果不是登錄頁,就要看看本地有沒有用戶信息,看看cookie中有沒有用戶信息(不一定是token,也可能是localstorage)。如果有用戶信息,放行。如果沒有用戶信息,就調(diào)用接口去獲取登錄信息,然后后面還有一點代碼,涉及到了動態(tài)添加路由(這里先說到這,后面具體說動態(tài)添加權(quán)限路由的事)。獲取到用戶信息后放行。如果在獲取用戶信息的過程中報錯,則回到登錄頁

無token:先看看用戶要進(jìn)入的頁面是不是在白名單內(nèi),一般登錄、注冊、忘記密碼都是在白名單內(nèi)的,這些頁面,在無token的情況下也是直接放行。如果不在白名單內(nèi),滾回登錄頁。

以上就是element-admin的登錄邏輯了。不知道能否幫助到你,但是寫下來,讓自己的思路更清晰,也是不錯的。

下面來說一下,element-admin的動態(tài)權(quán)限路由,顯示側(cè)邊欄是什么邏輯

首先要了解一下,側(cè)邊欄是如何渲染出來的,看看layout/components/slibar/index.vue有這樣一段代碼:

計算屬性中有這樣一段代碼:

routes() {

return this.$router.options.routes

},

這個routes,是路由的元信息!!!是一個數(shù)組

看到這就應(yīng)該明白,側(cè)邊欄是如何渲染出來的,

再來看看router.js里的代碼:

import Vue from 'vue'

import Router from 'vue-router'

Vue.use(Router)

/* Layout */

import Layout from '@/layout'

/**

* 注意: 子菜單只在路由子菜單時出現(xiàn)。長度> = 1

* 參考網(wǎng)址: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html

*

* hidden: true 如果設(shè)置為true,項目將不會顯示在側(cè)欄中(默認(rèn)為false)

* alwaysShow: true 如果設(shè)置為true,將始終顯示根菜單

* 如果不設(shè)置alwaysShow, 當(dāng)項目有多個子路由時,它將成為嵌套模式,否則不顯示根菜單

* redirect: noRedirect 如果設(shè)置noRedirect,則不會在面包屑中重定向

* name:'router-name' the name is used by (must set!!!)

* meta : {

roles: ['admin','editor'] 控制頁面角色(可以設(shè)置多個角色)

title: 'title' 名稱顯示在側(cè)邊欄和面包屑(推薦集)

icon: 'svg-name' 圖標(biāo)顯示在側(cè)欄中

breadcrumb: false 如果設(shè)置為false,則該項將隱藏在breadcrumb中(默認(rèn)為true)

activeMenu: '/example/list' 如果設(shè)置路徑,側(cè)欄將突出顯示您設(shè)置的路徑

}

*/

/**

* constantRoutes

* 沒有權(quán)限要求的基本頁

* 所有角色都可以訪問

* 不需要動態(tài)判斷權(quán)限的路由

*/

export const constantRoutes = [

{

path: '/login',

component: () => import('@/views/login/index'),

hidden: true

},

{

path: '/404',

component: () => import('@/views/404'),

hidden: true

},

{

path: '/',

component: Layout,

redirect: '/self',

children: [{

path: 'self',

name: 'Self',

component: () => import('@/views/self/index'),

meta: { title: '首頁', icon: 'dashboard' }

}]

},

{

path: '/example',

component: Layout,

redirect: '/example/table',

name: 'Example',

meta: { title: 'Example', icon: 'example' },

children: [

{

path: 'table',

name: 'Table',

component: () => import('@/views/table/index'),

meta: { title: 'Table', icon: 'table'}

},

{

path: 'tree',

name: 'Tree',

component: () => import('@/views/tree/index'),

meta: { title: 'Tree', icon: 'tree',breadcrumb: true},

hidden: false,//在側(cè)邊欄上顯示 true為不顯示 當(dāng)父路由的字路由為1個時,不顯示父路由,直接顯示子路由

alwaysShow:false,//默認(rèn)是false 設(shè)置為true時會忽略設(shè)置的權(quán)限 一致顯示在跟路由上

}

]

},

{

path: '/form',

component: Layout,

children: [

{

path: 'index',

name: 'Form',

component: () => import('@/views/form/index'),

meta: { title: 'Form', icon: 'form' }

}

]

},

{

path: '/nested',

component: Layout,

redirect: '/nested/menu1',

name: 'Nested',

meta: {

title: 'Nested',

icon: 'nested'

},

children: [

{

path: 'menu1',

component: () => import('@/views/nested/menu1/index'), // Parent router-view

name: 'Menu1',

meta: { title: 'Menu1' },

children: [

{

path: 'menu1-1',

component: () => import('@/views/nested/menu1/menu1-1'),

name: 'Menu1-1',

meta: { title: 'Menu1-1' }

},

{

path: 'menu1-2',

component: () => import('@/views/nested/menu1/menu1-2'),

name: 'Menu1-2',

meta: { title: 'Menu1-2' },

children: [

{

path: 'menu1-2-1',

component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),

name: 'Menu1-2-1',

meta: { title: 'Menu1-2-1' }

},

{

path: 'menu1-2-2',

component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),

name: 'Menu1-2-2',

meta: { title: 'Menu1-2-2' }

}

]

},

{

path: 'menu1-3',

component: () => import('@/views/nested/menu1/menu1-3'),

name: 'Menu1-3',

meta: { title: 'Menu1-3' }

}

]

},

]

},

{

path: 'external-link',

component: Layout,

children: [

{

path: 'https://panjiachen.github.io/vue-element-admin-site/#/',

meta: { title: 'External Link', icon: 'link' }

}

]

},

{

path: '/self',

component: Layout,

children: [

{

path: 'index',

name: 'self',

component: () => import('@/views/self'),

meta: { title: 'self', icon: 'form' }

}

]

},

// 404頁面必須放在最后!!

// { path: '*', redirect: '/404', hidden: true }

]

// 創(chuàng)建路由

const createRouter = () => new Router({

// mode: 'history', // 需要服務(wù)支持

scrollBehavior: () => ({ y: 0 }),

routes: constantRoutes

})

var router = createRouter()

// 重置路由

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465

export function resetRouter() {

const newRouter = createRouter()

router.matcher = newRouter.matcher // reset router

}

//異步掛載的路由

//動態(tài)需要根據(jù)權(quán)限加載的路由表

export const asyncRouterMap = [

{

path: '/permission',

component: Layout,

name: 'permission',

redirect: '/permission/index222',

meta: {title:'permission', role: ['admin','super_editor'] }, //頁面需要的權(quán)限

children: [

{

path: 'index222',

component: () => import('@/views/self'),

name: 'index222',

meta: {title:'權(quán)限測試1',role: ['admin','super_editor'] } //頁面需要的權(quán)限

},

{

path: 'index333',

component: () => import('@/views/self'),

name: 'index333',

meta: {title:'權(quán)限測試2',role: ['admin','super_editor'] } //頁面需要的權(quán)限

}

]

},

{ path: '*', redirect: '/404', hidden: true }

];

export default router

注意以上代碼中紅色的代碼,這個routes中分兩塊路由配置,一塊是固定的,無權(quán)限的路由配置,也就是不管是管理員身份,還是超級管理員身份,都會顯示的路由配置。

第二塊是,帶權(quán)限的路由配置,根據(jù)用戶權(quán)限來顯示側(cè)邊欄。注意,帶權(quán)限的配置里的meta中都有role項,代表是權(quán)限

首先,我們在獲取用戶信息時,會得到這個用戶有哪些權(quán)限,是一個數(shù)組,假如是這樣的

commit('SET_ROLES',['admin','super_editor']);//自定義權(quán)限

這個用戶的權(quán)限有這些(admin、super_editor),然后再根據(jù)用戶權(quán)限來篩選出符合的動態(tài)添加的路由,

什么時候篩選呢?

這就用到登錄時的攔截器了,上面遇到過,就在哪執(zhí)行,來看看那里都是寫了一些什么代碼:

拿到這看看:

// 獲得用戶信息

await store.dispatch('user/getInfo');

//實際是請求用戶信息后返回,這里是模擬數(shù)據(jù),直接從store中取

const roles=store.getters.roles;

store.dispatch('permission/GenerateRoutes', { roles }).then(() => { // 生成可訪問的路由表

router.addRoutes(store.getters.addRouters); // 動態(tài)添加可訪問路由表

router.options.routes=store.getters.routers;

next({ ...to, replace: true });// hack方法 確保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record

})

routes其實就是上面的兩個權(quán)限組成的數(shù)組,然后傳入了GenerateRoutes方法內(nèi),(注意es6語法,看不懂的去了解一下es6),再看看GenerateRoutes中的代碼:

import { asyncRouterMap, constantRoutes } from '@/router';

function hasPermission(roles, route) {

if (route.meta && route.meta.role) {

return roles.some(role => route.meta.role.indexOf(role) >= 0)

} else {

return true

}

}

const permission = {

namespaced: true,

state: {

routers: constantRoutes,

addRouters: []

},

mutations: {

SET_ROUTERS: (state, routers) => {

state.addRouters = routers;

state.routers = constantRoutes.concat(routers);

}

},

actions: {

GenerateRoutes({ commit }, data) {//roles是用戶所帶的權(quán)限

return new Promise(resolve => {

const { roles } = data;

const accessedRouters = asyncRouterMap.filter(v => {

// if (roles.indexOf('admin') >= 0) {

// return true;

// };

if (hasPermission(roles, v)) {

if (v.children && v.children.length > 0) {

v.children = v.children.filter(child => {

if (hasPermission(roles, child)) {

return child

}

return false;

});

return v

} else {

return v

}

}

return false;

});

commit('SET_ROUTERS', accessedRouters);

resolve();

})

}

}

};

export default permission;

GenerateRoutes方法辦了一件事,就是把動態(tài)路由配置里符合用戶權(quán)限的配置篩選出來,組成一個數(shù)組,然后,和固定路由合并到了一起,存到了vuex中,

然后調(diào)用了這兩句代碼:

router.addRoutes(store.getters.addRouters); // 動態(tài)添加可訪問路由表

router.options.routes=store.getters.routers;

router.addRoutes()方法是,動態(tài)添加路由配置,參數(shù)是符合路由配置的數(shù)組,

然后將路由元信息,變成合并后的路由元信息,因為渲染側(cè)邊欄需要用到,

這兩句代碼,順序不能變,缺一不可,缺了addRoutes,點擊側(cè)邊欄的動態(tài)路由會無反應(yīng),缺了options,側(cè)邊欄顯示不出來動態(tài)添加的路由!!!!

以上就是element-admin的動態(tài)路由了,睡覺。。。。

標(biāo)簽:vue,admin,router,element,meta,store,import,path,路由

來源: https://www.cnblogs.com/fqh123/p/11094296.html

總結(jié)

以上是生活随笔為你收集整理的activemenu怎么拼 vue_vue-element-admin登录逻辑,以及动态添加路由,显示侧边栏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。