从零开始vue3+vite+ts+pinia+router4后台管理(3)-动态路由

从零开始vue3+vite+ts+pinia+router4后台管理(3)-动态路由

项目地址

项目git地址

我们在做项目中经常遇到有后端返回的文件路径(比如order/orderList),然后前端根据获取的路由数组动态加载路由,今天我们就看看怎么样实现的吧!本项目vue版本vue3 vue-router4 pinia Vite 完成的

实现思路

  1. 在路由钩子里面判断是否首次进入系统(permission.ts)

  2. init为true说明已经获取过路由,就直接放行,init为false则向后台请求用户路由

  3. 获取路由

  4. 解析路由,存储权限

  5. 使用router的api addRoute拼接路由

  6. 存储路由

  7. init改为true,路由初始化完成

  8. 放行路由

image-20230928140554125

###1 引入vue-router 设置静态路由 登陆,首页等。。。

router/index.ts

import {createRouter, createWebHistory} from 'vue-router'
import Layout from '@/layout/index.vue'
//constantRoutes 静态路由 登陆,首页等。。。
export const constantRoutes = [
    {
        path: '/',//默认首页
        redirect: '/dashboard',
        hidden: true,
    },
    {
        path: "/dashboard",
        name: 'Dashboard',
        meta: {
            title: '首页',
            icon: "House",
        },
        component: Layout
    },
    {
        path: "/login",
        name: "Login",
        meta: {
            title: '登录'
        },
        component: () => import('@/views/user/login/index.vue'),
        hidden: true
    },
    {
        path: '/:pathMatch(.*)*',// 此写法解决动态路由页面刷新的 warning 警告
        component: () => import('@/views/user/error-page/404.vue'),
        hidden: true
    },
]
//动态路由 asyncRoutes
export const asyncRoutes = []

const router = createRouter({
    history: createWebHistory(),// HTML5的history模式
    routes: constantRoutes
})

export default router

2 获取后端路由数组,动态挂载路由permission.ts

permission.ts入口权限判断ts 和mian.ts同一级

import router from './router/index'
import { useUserStore } from '@/store/user'
import { usePermissionStore } from '@/store/permission'
import {getToken} from '@/utils/storage.ts'
import NProgress from 'nprogress'
import'nprogress/nprogress.css'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // 白名单
router.beforeEach(async (to) => {
    NProgress.start();
    document.title = `${to.meta.title} | vu3dny-admin`
    const hasToken = getToken('Access-Token')
    const userStore = useUserStore()
    const permissionStore = usePermissionStore()
    if (hasToken) {//判断token是否存在 存在即为已经登录
        if (to.path !== "/login") {
            if (userStore.init) { // 获取了动态路由 init一定true,就无需再次请求 直接放行
                return true
            }else {
                // init为false,一定没有获取动态路由,就跳转到获取动态路由的方法
                const result = await userStore.getInfo() //获取路由
                const accessRoutes = await permissionStore.generateRoutes(result.menus) 				//解析路由,存储路由
                // console.log(accessRoutes);
                // 动态挂载路由
                accessRoutes.forEach((route) => {
                    router.addRoute(route)
                })
                userStore.init = true//init改为true,路由初始化完成
                return { ...to, replace: true }// hack方法 确保addRoute已完成

            }
        }else {
            NProgress.done()
            return '/'
        }

    }else {
        // 白名单,直接放行
        if (whiteList.indexOf(to.path) > -1) return true
        // 非白名单,去登录
        else return '/login'
        NProgress.done()
    }
})
router.afterEach(() => {
    // finish progress bar
    NProgress.done()
})

3 递归解析路由 根据后端返回文件路径匹配路由

import.meta.glob的妙用:Vite是一个现代工具,你主要使用ES模块。而Vite用方便的工具扩展了全局import.meta 对象。例如,它添加了一个import.meta.glob 函数,允许你从路径中解析文件。比如后端返回的是oder/orderList 路由 需要前端匹配 你需要在views文件夹 新建一个order文件夹 然后文件夹新建一个orderList.vue

const modules = import.meta.glob('@/views/**/**.vue')

router的componentcomponent = modules[/src/views${e.url}]

当然 如果你用的是vue2 vueCli构建的vue项目 你可以用 require引入 import.meta.glob只适用于Vite

store/permission.ts 生成动态路由权限

import {defineStore} from 'pinia'
import {constantRoutes} from '@/router'
import Layout from '@/layout/index.vue'
const modules = import.meta.glob('@/views/**/**.vue')
// console.log(modules);
export const filterAsyncRoutes = (routerList) => {
    //进行递归解析
    //routerList 后端获取的路由
    const res = []
    // console.log(testData);
    routerList.forEach(e => {
        // console.log(e.component);
        let e_new = {
            path: e.url,
            name: e.menuName,
            meta: {
                title: e.menuName,
                icon: e.icon
            },
             component: null

        }
        if (e.menuType === 'M') {
            e_new.component = Layout
        }else {
            // console.log("22222",e.url);
            e_new.component = modules[`/src/views${e.url}/index.vue`]
        }
        // console.log(e_new);
        if (e.children && e.children!=null) {
            const children = filterAsyncRoutes(e.children)
            // 保存权限
            e_new = { ...e_new, children: children }
        }

        res.push(e_new)
    })
    // console.vlog("111",res);
    return res
}

export const usePermissionStore = defineStore('permission', {
    id: 'permission', // id必填,且需要唯一
    state: () => {
        return {
            routes: [],//全部路由
            addRoutes: []//后端增加的路由
        }
    },
    actions: {
        generateRoutes(routes) {
            // console.log(routes);
            let routerList = JSON.parse(JSON.stringify(routes))
            // console.log(routerList);
            return new Promise((resolve) => {
                
                const accessedRoutes = filterAsyncRoutes(routerList)
                // console.log(accessedRoutes);
                this.addRoutes = accessedRoutes
                // console.log("111",accessedRoutes);
                this.routes = constantRoutes.concat(accessedRoutes)
                resolve(accessedRoutes)
            })

        }
    }
})
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是搭建后台管理系统的简单步骤: 1. 创建项目 使用 Vue CLI 创建项目,选择 vue3 preset,安装完成后进入项目目录。 ``` vue create my-project cd my-project ``` 2. 安装依赖包 安装 vitevue-router 和 element-plus。 ``` npm install vite vue-router@4 element-plus --save ``` 安装 pinia 和 echarts。 ``` npm install pinia echarts@5 --save ``` 3. 配置 vite 在根目录下创建 `vite.config.js` 文件,配置 alias 和 server。 ```js import path from 'path' import { defineConfig } from 'vite' export default defineConfig({ resolve: { alias: { '@': path.resolve(__dirname, 'src'), }, }, server: { port: 3000, open: true, }, }) ``` 4. 配置路由 在 `src` 目录下创建 `router` 文件夹,并创建 `index.js` 文件,配置路由。 ```js import { createRouter, createWebHistory } from 'vue-router' import Home from '@/views/Home.vue' const routes = [ { path: '/', name: 'Home', component: Home, }, ] const router = createRouter({ history: createWebHistory(), routes, }) export default router ``` 在 `src` 目录下的 `main.js` 中引入路由。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' const app = createApp(App) app.use(router) app.mount('#app') ``` 5. 配置状态管理 在 `src` 目录下创建 `store` 文件夹,并创建 `index.js` 文件,配置状态管理。 ```js import { createPinia } from 'pinia' const store = createPinia() export default store ``` 在 `src` 目录下的 `main.js` 中引入状态管理。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' const app = createApp(App) app.use(router) app.use(store) app.mount('#app') ``` 6. 配置 UI 框架 在 `src` 目录下的 `main.js` 中引入 element-plus。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' const app = createApp(App) app.use(router) app.use(store) app.use(ElementPlus) app.mount('#app') ``` 7. 配置 echarts 在 `src` 目录下的 `main.js` 中引入 echarts。 ```js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' import * as echarts from 'echarts' const app = createApp(App) app.use(router) app.use(store) app.use(ElementPlus) app.config.globalProperties.$echarts = echarts app.mount('#app') ``` 8. 创建页面 在 `src` 目录下创建 `views` 文件夹,并创建页面组件。 9. 创建布局 在 `src` 目录下创建 `layouts` 文件夹,并创建布局组件。 10. 配置路由和布局 在 `router/index.js` 中配置路由和布局。 ```js import { createRouter, createWebHistory } from 'vue-router' import Layout from '@/layouts/Layout.vue' import Home from '@/views/Home.vue' const routes = [ { path: '/', component: Layout, children: [ { path: '', name: 'Home', component: Home, }, ], }, ] const router = createRouter({ history: createWebHistory(), routes, }) export default router ``` 11. 运行项目 在项目根目录下运行 `npm run dev`,打开浏览器访问 `http://localhost:3000` 查看效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值