vue-router vuex-oidc动态路由实例及功能详解

 更新时间:2023年11月22日 09:36:32   作者:charlotteeeeeee  
这篇文章主要为大家介绍了vue-router vuex-oidc动态路由实例及功能详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

功能描述

1:通过接口获取当前应用的所有菜单基本信息及路由信息

2:vuex-oidc为可以检测当前是否获取登录信息,如果没有,则会跳转到登录页面

3:通过接口拿到的路由信息辅助指定到对应vue页面,完成页面及路由的一一绑定

store.js

1:完成oidc相应配置 详细参见

2:建立储存方法及获取接口动态菜单

import { createStore } from 'vuex'
import { vuexOidcCreateStoreModule } from 'vuex-oidc'
import gql from "graphql-tag";//graphQL语法标签,axios可删除
import apolloProvider from "@/assets/js/apolloclient.js";//接口发起client 可按需换成axios
let g = window.Global;
let oidcSettings = {};
//window.Global会携带所有可用信息,此处为了方便本地调试加
//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: [], //非树型结构
        menulist: [], //树型结构
        asyncRoutestMark: false,
    },
    mutations: {
        // 单层级菜单,没有父子结构,取决于接口返回信息,按需取舍
        setCanvasmenus(state, data) {
            state.canvasmenus = data
        },
        // 树型菜单
        setMenulist(state, data) {
            state.menulist = data
        },
        // 标记是否已经发起过菜单获取动作,避免二次发起
        setAsyncRoutestMark(state, data) {
            state.asyncRoutestMark = data
        },
    },
    getters: {
        //本处做一次些菜单字段处理,可以按照自己项目做调整,可忽略
        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发起一个请求获取动态菜单信息
        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 相关配置,各种登录状态及相应返回,详细说明见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";//将单层菜单整理层树结构,可忽略
const publicRoutes = [{
        path: '/oidc-callback',//oidc登录后回调,可忽略
        name: 'OidcCallback',
        component: () =>
            import ('@/views/oidc/OidcCallback.vue')
    },
    {
        path: '/oidc-silent',//oidc静态登录,可忽略
        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, //静态路由
});
// 动态路由获取到数据后加入routes
const routerData = (result) => {
    let currenRoutes = router.options.routes;
    // 获取组件中所有vue文件
    let modules =
        import.meta.glob('../views/**/*.vue');
    if (result) {
        result.forEach((item, index) => {
            // has用于判断当前路由中是否已经具有,避免重复
            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);
            }
        });
    }
};
// 动态路由获取
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动态路由实例及功能详解的详细内容,更多关于vue-router vuex-oidc动态路由的资料请关注脚本之家其它相关文章!

相关文章

  • Vue-cli创建项目从单页面到多页面的方法

    Vue-cli创建项目从单页面到多页面的方法

    本篇文章主要介绍了Vue-cli创建项目从单页面到多页面的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • element动态路由面包屑的实现示例

    element动态路由面包屑的实现示例

    本文主要介绍了element动态路由面包屑的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • element-ui组件table实现自定义筛选功能的示例代码

    element-ui组件table实现自定义筛选功能的示例代码

    这篇文章主要介绍了element-ui组件table实现自定义筛选功能的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • Vue中v-bind原理深入探究

    Vue中v-bind原理深入探究

    这篇文章主要给大家分享了 v-bind的使用和注意需要注意的点,下面文章围绕 v-bind指令的相关资料展开内容且附上详细代码 需要的小伙伴可以参考一下,希望对大家有所帮助
    2022-10-10
  • Vite开发环境搭建详解

    Vite开发环境搭建详解

    Vite是一款非常轻量级的Web开发框架,它可以帮助开发者快速搭建一个开发环境。Vite搭建的开发环境可以提供更快的编译速度,更少的配置,更好的性能和更多的开发者友好性,使开发者可以更快地构建出功能强大的Web应用程序。
    2023-02-02
  • vue中marker被识别点击的过程场景分析

    vue中marker被识别点击的过程场景分析

    这篇文章主要介绍了vue中marker被识别点击的过程场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • 在vue中如何封装G2图表

    在vue中如何封装G2图表

    这篇文章主要介绍了在vue中如何封装G2图表,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • 使用Vue-scroller页面input框不能触发滑动的问题及解决方法

    使用Vue-scroller页面input框不能触发滑动的问题及解决方法

    这篇文章主要介绍了使用Vue-scroller页面input框不能触发滑动的问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Vue项目如何关闭语法检查

    Vue项目如何关闭语法检查

    这篇文章主要介绍了Vue项目如何关闭语法检查问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • 前端通过vue调用后端接口导出excel表格基本步骤

    前端通过vue调用后端接口导出excel表格基本步骤

    在Vue前端项目中,可通过axios库发送请求至后端获取Excel下载链接,文中通过代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-10-10

最新评论