vue-router vuex-oidc動(dòng)態(tài)路由實(shí)例及功能詳解
功能描述
1:通過接口獲取當(dāng)前應(yīng)用的所有菜單基本信息及路由信息
2:vuex-oidc為可以檢測(cè)當(dāng)前是否獲取登錄信息,如果沒有,則會(huì)跳轉(zhuǎn)到登錄頁面
3:通過接口拿到的路由信息輔助指定到對(duì)應(yīng)vue頁面,完成頁面及路由的一一綁定
store.js
1:完成oidc相應(yīng)配置 詳細(xì)參見
2:建立儲(chǔ)存方法及獲取接口動(dòng)態(tài)菜單
import { createStore } from 'vuex' import { vuexOidcCreateStoreModule } from 'vuex-oidc' import gql from "graphql-tag";//graphQL語法標(biāo)簽,axios可刪除 import apolloProvider from "@/assets/js/apolloclient.js";//接口發(fā)起client 可按需換成axios let g = window.Global; let oidcSettings = {}; //window.Global會(huì)攜帶所有可用信息,此處為了方便本地調(diào)試加 //oidc相關(guān)配置參見1參考鏈接 if (!g) { g = { oauth2_uri: 'https://devel.ketanyun.cn/sso/oauth2', oauth2_logout_uri: 'https://devel.ketanyun.cn/sso/logout', }; } window.Global = {...g } let authority = g.oauth2_uri; let silentRedirectUri = (window.location.origin + g.contextpath + "/oidc-silent") //oidc登錄配置相關(guān)信息,按需取舍 oidcSettings = { authority: authority, metadata: { issuer: authority, authorization_endpoint: authority + "/authorize", userinfo_endpoint: authority + "/userinfo", end_session_endpoint: g.oauth2_logout_uri + "?redirect_uri=" + window.location.origin + g.contextpath, jwks_uri: authority + "/jwks.json" }, clientId: g.client_id, redirectUri: window.location.origin + g.contextpath + "/oidc-callback", responseType: "id_token token", scope: "data openid ", automaticSilentRenew: true, silentRedirectUri: silentRedirectUri, silentRequestTimeout: 1000 }; export default createStore({ state: { canvasmenus: [], //非樹型結(jié)構(gòu) menulist: [], //樹型結(jié)構(gòu) asyncRoutestMark: false, }, mutations: { // 單層級(jí)菜單,沒有父子結(jié)構(gòu),取決于接口返回信息,按需取舍 setCanvasmenus(state, data) { state.canvasmenus = data }, // 樹型菜單 setMenulist(state, data) { state.menulist = data }, // 標(biāo)記是否已經(jīng)發(fā)起過菜單獲取動(dòng)作,避免二次發(fā)起 setAsyncRoutestMark(state, data) { state.asyncRoutestMark = data }, }, getters: { //本處做一次些菜單字段處理,可以按照自己項(xiàng)目做調(diào)整,可忽略 menuList(state) { let list = state.menulist ? (JSON.parse(JSON.stringify(state.menulist))) : []; list.map((item) => { const arr = item.path.split('/'); arr.splice(1, 1); item.routerpath = arr.join('/'); }) list = list && list.length ? list : ''; return list }, getterStorecanvasmenu(state) { return state.canvasmenus } }, actions: { //異步獲取菜單信息,本處使用的granphQL-apolloclient,可以按需將其換成axios //簡(jiǎn)而言之,此處的action發(fā)起一個(gè)請(qǐng)求獲取動(dòng)態(tài)菜單信息 async getMenuList({ state }) { return apolloProvider.clients.builtinclient.query({ client: 'builtinclient', fetchPolicy: "no-cache", query: gql `query canvasmenus{ canvasmenus { parent name text description uri icon visible } }` }) } }, modules: { //oidc 相關(guān)配置,各種登錄狀態(tài)及相應(yīng)返回,詳細(xì)說明見1參考鏈接 oidcStore: vuexOidcCreateStoreModule( oidcSettings, { namespaced: true, dispatchEventsOnWindow: true }, { userLoaded: (user) => console.log('OIDC user is loaded:', user), userUnloaded: () => console.log('OIDC user is unloaded'), accessTokenExpiring: () => console.log('Access token will expire'), accessTokenExpired: () => console.log('Access token did expire'), silentRenewError: () => console.log('OIDC user is unloaded'), userSignedOut: () => console.log('OIDC user is signed out'), oidcError: (payload) => console.log('OIDC error', payload) } ) } })
router.js
import { createRouter, createWebHistory } from 'vue-router' import { vuexOidcCreateRouterMiddleware } from 'vuex-oidc' import store from "@/store/index";//引入store import { formSideTree } from "@/utils/index.js";//將單層菜單整理層樹結(jié)構(gòu),可忽略 const publicRoutes = [{ path: '/oidc-callback',//oidc登錄后回調(diào),可忽略 name: 'OidcCallback', component: () => import ('@/views/oidc/OidcCallback.vue') }, { path: '/oidc-silent',//oidc靜態(tài)登錄,可忽略 name: 'Oidcsilent', component: () => import ('@/views/oidc/OidcRenew.vue') }, { path: '/', name: "viewindex", component: () => import ('@/views/view.vue'),//項(xiàng)目主入口模板 meta: { requiresAuth: true }, } ] const router = createRouter({ history: createWebHistory(contentPath), routes: publicRoutes, //靜態(tài)路由 }); // 動(dòng)態(tài)路由獲取到數(shù)據(jù)后加入routes const routerData = (result) => { let currenRoutes = router.options.routes; // 獲取組件中所有vue文件 let modules = import.meta.glob('../views/**/*.vue'); if (result) { result.forEach((item, index) => { // has用于判斷當(dāng)前路由中是否已經(jīng)具有,避免重復(fù) let has = currenRoutes.some((it) => it.path == item.path); if (!has && item.routerpath) { //多語言 let menutitlei18n = 'contact.menu.menu' + index; //多語言 if (item.description && item.description.indexOf(',') >= 0) { let mitems = item.description.split(','); if (mitems[0]) { menutitlei18n = 'contact.menu.' + mitems[0] } } // 多語言end // 僅作為viewindex子組件 router.addRoute("viewindex", { path: `${item.routerpath}`, name: item.name, meta: { title: item.name, requiresAuth: true, menutitlei18n, }, component: modules[`../views${item.path}.vue`] }); } if (item.children && item.children.length) { routerData(item.children); } }); } }; // 動(dòng)態(tài)路由獲取 router.beforeEach((to, from, next) => { if (!(to.matched && to.matched.length)) { if (to.path !== '/') { next({ path: '/' }); return } } const requiresAuth = to.matched.some(record => record.meta.requiresAuth); if (requiresAuth) { vuexOidcCreateRouterMiddleware(store, 'oidcStore')(to, from, async() => { if (!store.state.asyncRoutestMark) { //是否已完成路由添加 let navigationList = []; store.commit('setCanvasmenus', []) await store.dispatch('getMenuList').then((res) => { if (res ? .data ? .canvasmenus) { res ? .data ? .canvasmenus ? .map((item) => { if (item.uri) { if (item.uri && item.uri.split("vue://")[1] && item.uri.split("vue://")[1].indexOf("@") >= 0) { item.path = item.uri.split("vue://")[1].split("@")[0]; let arr = item.path.split('/'); arr.splice(1, 1); item.routerpath = arr.join('/') } } }); //存入store,菜單不必再二次請(qǐng)求 store.commit('setCanvasmenus', res ? .data ? .canvasmenus); navigationList = formSideTree(res ? .data ? .canvasmenus); } }) routerData(navigationList) store.commit('setAsyncRoutestMark', true) // 添加路由后更改標(biāo)識(shí)為true next({...to, replace: true }) //路由進(jìn)行重定向放行 } else { next(); } }) } else { next(); } }) export default router
以上就是vue-router vuex-oidc動(dòng)態(tài)路由實(shí)例及功能詳解的詳細(xì)內(nèi)容,更多關(guān)于vue-router vuex-oidc動(dòng)態(tài)路由的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue中 v-if/v-show/插值表達(dá)式導(dǎo)致閃現(xiàn)的原因及解決辦法
在開發(fā)過程中經(jīng)常會(huì)發(fā)現(xiàn)當(dāng)頁面明明不應(yīng)該出現(xiàn)的元素或內(nèi)容會(huì)閃現(xiàn)一下然后消失,這篇文章給大家分享Vue中 v-if/v-show/插值表達(dá)式導(dǎo)致閃現(xiàn)的原因及解決辦法,一起看看吧2018-10-10Vue 打包的靜態(tài)文件不能直接運(yùn)行的原因及解決辦法
這篇文章主要介紹了Vue 打包的靜態(tài)文件不能直接運(yùn)行的原因及解決辦法,幫助大家更好的理解和學(xué)習(xí)vue框架,感興趣的朋友可以了解下2020-11-11vue3?+?antv/x6實(shí)現(xiàn)流程圖的全過程
隨著互聯(lián)網(wǎng)的發(fā)展,越來越多的應(yīng)用需要實(shí)現(xiàn)流程圖的制作,如工作流程圖、電路圖等,文中通過代碼以及圖文將實(shí)現(xiàn)的過程介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-06-06vue使用echarts實(shí)現(xiàn)三維圖表繪制
這篇文章主要為大家詳細(xì)介紹了vue如何在項(xiàng)目中使用echarts實(shí)現(xiàn)三維圖表的繪制,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2023-08-08vuex如何在非組件中調(diào)用mutations方法
這篇文章主要介紹了vuex如何在非組件中調(diào)用mutations方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03大前端代碼重構(gòu)之事件攔截iOS?Flutter?Vue示例分析
這篇文章主要為大家介紹了大前端代碼重構(gòu)之事件攔截iOS?Flutter?Vue示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04vue3.0中使用element UI表單遍歷校驗(yàn)問題解決
本文主要介紹了vue3.0中使用element UI表單遍歷校驗(yàn)問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04手把手帶你安裝vue-cli并創(chuàng)建第一個(gè)vue-cli應(yīng)用程序
vue-cli這個(gè)構(gòu)建工具大大降低了webpack的使用難度,支持熱更新,有webpack-dev-server的支持,相當(dāng)于啟動(dòng)了一個(gè)請(qǐng)求服務(wù)器,給你搭建了一個(gè)測(cè)試環(huán)境,下面這篇文章主要給大家介紹了關(guān)于安裝vue-cli并創(chuàng)建第一個(gè)vue-cli應(yīng)用程序的相關(guān)資料,需要的朋友可以參考下2022-08-08vue框架制作購物車小球動(dòng)畫效果實(shí)例代碼
最近在學(xué)習(xí)前端制作了一個(gè)購物車小球的動(dòng)畫效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-09-09