vue-router vuex-oidc動態(tài)路由實例及功能詳解
功能描述
1:通過接口獲取當前應用的所有菜單基本信息及路由信息
2:vuex-oidc為可以檢測當前是否獲取登錄信息,如果沒有,則會跳轉(zhuǎn)到登錄頁面
3:通過接口拿到的路由信息輔助指定到對應vue頁面,完成頁面及路由的一一綁定
store.js
1:完成oidc相應配置 詳細參見
2:建立儲存方法及獲取接口動態(tài)菜單
import { createStore } from 'vuex' import { vuexOidcCreateStoreModule } from 'vuex-oidc' import gql from "graphql-tag";//graphQL語法標簽,axios可刪除 import apolloProvider from "@/assets/js/apolloclient.js";//接口發(fā)起client 可按需換成axios let g = window.Global; let oidcSettings = {}; //window.Global會攜帶所有可用信息,此處為了方便本地調(diào)試加 //oidc相關配置參見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登錄配置相關信息,按需取舍 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: { // 單層級菜單,沒有父子結(jié)構(gòu),取決于接口返回信息,按需取舍 setCanvasmenus(state, data) { state.canvasmenus = data }, // 樹型菜單 setMenulist(state, data) { state.menulist = data }, // 標記是否已經(jīng)發(fā)起過菜單獲取動作,避免二次發(fā)起 setAsyncRoutestMark(state, data) { state.asyncRoutestMark = data }, }, getters: { //本處做一次些菜單字段處理,可以按照自己項目做調(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 //簡而言之,此處的action發(fā)起一個請求獲取動態(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 相關配置,各種登錄狀態(tài)及相應返回,詳細說明見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'),//項目主入口模板 meta: { requiresAuth: true }, } ] const router = createRouter({ history: createWebHistory(contentPath), routes: publicRoutes, //靜態(tài)路由 }); // 動態(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用于判斷當前路由中是否已經(jīng)具有,避免重復 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); } }); } }; // 動態(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,菜單不必再二次請求 store.commit('setCanvasmenus', res ? .data ? .canvasmenus); navigationList = formSideTree(res ? .data ? .canvasmenus); } }) routerData(navigationList) store.commit('setAsyncRoutestMark', true) // 添加路由后更改標識為true next({...to, replace: true }) //路由進行重定向放行 } else { next(); } }) } else { next(); } }) export default router
以上就是vue-router vuex-oidc動態(tài)路由實例及功能詳解的詳細內(nèi)容,更多關于vue-router vuex-oidc動態(tài)路由的資料請關注腳本之家其它相關文章!
相關文章
Vue中 v-if/v-show/插值表達式導致閃現(xiàn)的原因及解決辦法
在開發(fā)過程中經(jīng)常會發(fā)現(xiàn)當頁面明明不應該出現(xiàn)的元素或內(nèi)容會閃現(xiàn)一下然后消失,這篇文章給大家分享Vue中 v-if/v-show/插值表達式導致閃現(xiàn)的原因及解決辦法,一起看看吧2018-10-10Vue 打包的靜態(tài)文件不能直接運行的原因及解決辦法
這篇文章主要介紹了Vue 打包的靜態(tài)文件不能直接運行的原因及解決辦法,幫助大家更好的理解和學習vue框架,感興趣的朋友可以了解下2020-11-11vuex如何在非組件中調(diào)用mutations方法
這篇文章主要介紹了vuex如何在非組件中調(diào)用mutations方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03大前端代碼重構(gòu)之事件攔截iOS?Flutter?Vue示例分析
這篇文章主要為大家介紹了大前端代碼重構(gòu)之事件攔截iOS?Flutter?Vue示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04手把手帶你安裝vue-cli并創(chuàng)建第一個vue-cli應用程序
vue-cli這個構(gòu)建工具大大降低了webpack的使用難度,支持熱更新,有webpack-dev-server的支持,相當于啟動了一個請求服務器,給你搭建了一個測試環(huán)境,下面這篇文章主要給大家介紹了關于安裝vue-cli并創(chuàng)建第一個vue-cli應用程序的相關資料,需要的朋友可以參考下2022-08-08