位置: IT常识 - 正文

Vue3动态路由(Vite+Vue3+TS+Mock)(vue3动态路由权限)

编辑:rootadmin
Vue3动态路由(Vite+Vue3+TS+Mock) 一、动态路由简介

推荐整理分享Vue3动态路由(Vite+Vue3+TS+Mock)(vue3动态路由权限),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:vue3动态路由刷新后页面空白,vue3动态路由刷新丢失,vue3动态路由导航菜单,vue3动态路由不生效,vue3动态路由权限,vue3动态路由不生效,vue3动态路由权限,vue3动态路由导航菜单,内容如对您有帮助,希望把文章链接给更多的朋友!

Vue通过路由进行页面管理,不同的路由绑定到不同的页面。一般来说,前端直接写好的路由为静态路由,在不修改代码的情况下,路由表是不会改变的。对于不需要动态改变路由表的网站,静态路由就已经足够了,但是当页面需要与权限进行绑定时,不同用户允许浏览的页面是不一样的,在这种情况下,静态路由就难以满足需求了。动态路由就是由后端根据场景生成的合适路由数据,前端获取此数据并进行解析,最后与固定不变的静态路由组合而成的路由。

本文将基于Vite+Vue3+TypeScript构建的Vue项目与mock模拟的后端接口,简单介绍Vue的动态路由配置。

此项目代码已上传至GitHub,链接如下:

https://github.com/XMNHCAS/VueDynamicRoute

二、创建Vite+Vue3+TS基础项目

首先使用以下命令创建项目

npm create vite 项目名 -- --template vue-ts

在刚刚创建的项目的目录下执行以下命令,安装vue初始的node依赖包 

npm i

参考示例如下:

项目创建完成后,在项目目录下执行以下命令,使用VSCode打开此项目。也可以直接在此目录下右键点击使用VSCode打开。

Code .

注意:使用VSCode编辑Vue+TS的项目,建议禁用Vetur,使用Volar插件。

三、项目初始化及静态路由配置 3.1、安装需要的Node Module 

接下来我们需要安装几个node模块:vue-router、axios和mock。其中vue-router是Vue的路由配置模块,axios是请求包,mock则是前端模拟api接口的包。

可依次执行以下命令,或修改package.json文件之后直接npm i。

安装vue-router和axios:

npm i vue-router axios -S

安装mockjs和vite-plugin-mock。由于本项目的mock主要用途仅为模拟后端数据接口,所以安装为开发依赖,若打包为生产环境则会失效。

npm i mockjs vite-plugin-mock -D3.2、创建需要的文件夹以及文件

首先我们打开src文件夹下的components文件,删除HelloWorld.vue。打开App.vue,将文件内容修改为以下代码:

<template> <router-view></router-view></template>

然后在src文件夹下分别创建router、utils、apis、views和mock文件夹,并在文件夹中创建如图所示的文件:

 

3.3、配置vue-router

/src/router/index.ts:此文件为路由配置文件,我们先在此创建初始的静态路由。

import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router'// 静态路由表const routes: Array<RouteRecordRaw> = [ { // 路由重定向配置 path: '/', redirect: '/Home' }, { path: '/Home', component: () => import('../views/HomePage.vue') }]// 路由对象const router = createRouter({ history: createWebHistory(), routes})export default router3.4、配置mock

/src/mock/index.ts:此文件为mock模拟接口配置,我们先创建一个测试接口,返回一个Hello World

import { MockMethod } from "vite-plugin-mock"const mock: Array<MockMethod> = [ { // 接口路径 url: '/api/test', // 接口方法 method: 'get', // 返回数据 response: () => { return { status: 200, message: 'success', data: 'Hello World' } } }]export default mock3.5、配置vite.config.ts

要使用mock,我们还需要在vite.config.ts文件下对mock进行配置,让vite启动的同时启动mock服务。

import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { viteMockServe } from 'vite-plugin-mock'// https://vitejs.dev/config/export default defineConfig({ plugins: [ vue(), // mock服务 viteMockServe({ supportTs: false, logger: false, mockPath: "./src/mock/", }), ]})3.6、配置axios

/src/utils/request.ts:此文件为axios配置文件,它将创建一个axios全局单例,由于本项目仅做最简单的演示,所以仅配置baseUrl,实际使用时可根据实际情况添加拦截器等功能。

import axios from 'axios'// axios对象const service = axios.create({ // axios请求基础URL // 由于本项目使用mock + vite-plugin-mock启动的mock服务,默认使用的端口号与页面一致 baseURL: "http://localhost:5173", timeout: 5000})export default service

/src/apis/index.ts:此文件为接口文件,接口统一放到此文件中。

import req from '../utils/request'/** * 测试接口 */// 测试用Hello Worldexport const TestApi = () => req({ url: '/api/test', method: 'get' })3.7、首页代码

/src/views/HomePage.vue:

<template> <h1>Home</h1></template><script lang="ts" setup>import { TestApi } from '../apis'TestApi().then(res => console.log(res)).catch(err => console.log(err))</script>3.8、配置main.tsimport { createApp } from 'vue'import './style.css'import App from './App.vue'import router from './router'const app = createApp(App)// 启用路由app.use(router)app.mount('#app')3.9、静态路由运行 

使用此命令运行,vite3默认的运行端口为5173。 

npm run dev

运行结果如下所示:

从右侧开发者工具中可以看出,我们模拟的test接口已经成功返回了数据,页面也正常根据路由跳转至Home页面。

四、配置动态路由4.1、配置动态路由接口

首先我们先在刚刚创建的mock接口文件(/src/mock/index.ts)中添加一个返回路由信息的路由接口,如下所示:

import { MockMethod } from "vite-plugin-mock"const mock: Array<MockMethod> = [ /** * 测试接口 */ { // 接口路径 url: '/api/test', // 接口方法 method: 'get', // 返回数据 response: () => { return { status: 200, message: 'success', data: 'Hello World' } } }, /** * 路由数据接口 */ { url: '/api/routes', method: 'get', response: () => { // 路由 const routes = [ { path: '/PageOne', name: 'PageOne', component: 'PageOne.vue' }, { path: '/PageTwo', name: 'PageTwo', component: 'PageTwo.vue' }, { path: '/PageThree', name: 'PageThree', component: 'PageThree.vue', } ] return { status: 200, message: 'success', data: routes } } }]export default mock

此接口返回三个页面的路由,根据这个接口的数据,我们在views文件夹中创建这三个页面。 

 

页面仅由一个h1标签组成,h1的内容为文件名。此外再加上一个按钮,用以跳转回Home页面。PageOne.vue代码如下:

<template> <h1>Page One</h1> <button @click="handleClick">Home</button></template><script lang="ts" setup>import { useRouter } from 'vue-router';const router = useRouter()const handleClick = () => router.push({ path: '/Home' })</script>

其余两个页面仅需修改h1标签的内容。

4.2、安装并配置pinia

我们的动态路由数据应由一个公共的地方进行管理,本文选用vue的状态管理器来实现这个功能。pinia是vue新一代的状态管理器,与vuex作用基本相同,但是功能比vuex更加强大。

Vue3动态路由(Vite+Vue3+TS+Mock)(vue3动态路由权限)

pinia官方文档:https://pinia.web3doc.top

首先在项目目录下执行以下命令,安装pinia:

npm i pinia -S

安装完成后,创建store文件夹,并在此文件夹下创建index.ts文件。

 /src/store/index.ts:

import { defineStore } from 'pinia'// pinia状态管理器export const useStore = defineStore('myStore', { state: () => { return {} }, getters: {}, actions: {}})

 完成基础配置后,需要在mian.ts中引入pinia,需要注意的是,pinia必须在vue-router之后引入。

main.ts

import { createApp } from 'vue'import './style.css'import App from './App.vue'import router from './router'import { createPinia } from 'pinia'const pinia = createPinia()const app = createApp(App)// 启用路由app.use(router)// 启用piniaapp.use(pinia)app.mount('#app')4.3、添加路由数据接口

/src/apis/index.ts:

import req from '../utils/request'/** * 测试接口 */// 测试用Hello Worldexport const TestApi = () => req({ url: '/api/test', method: 'get' })/** * 动态路由接口 */export const GetDynamicRoutes = () => req({ url: '/api/routes', method: 'get' })4.4、在pinia中添加配置项

由于我们使用的pinia存储我们的路由数据,所以我们需要在pinia的state中添加一个路由项(RouteRecordRaw类型的数组routes)。

我们在pinia的action中还需要添加一个根据路由数据加载动态路由的方法(addRoutes),路由数据和router对象由外部传入。外部传入router是为了避免循环调用router,毕竟需要进行加载动态路由的地方基本都有个router的示例对象,不过也可以直接在此方法里面直接调用router,并不影响结果,也不会报错。

加载路由的思路很简单,首先解析外部传入的路由数据,根据路由的数据类型生成对应的路由表,并存储到pinia中,然后直接遍历这个pinia中的路由表,使用router.addRoute()方法将路由加载进去。router.addRoute()方法还支持传如两个参数,这是为了在指定位置的路由中插入children,这种情况下第一个参数是父级路由的name,第二个参数就是要添加的children路由对象。本文的项目并没有做多层级的路由,所以使用一个参数即可。

vite使用动态路由,在动态导入组件的时候,需要注意不能将页面路径直接作为component导入,虽然开发环境一般是能正常加载,但是打包到生产环境的时候就会出错,所以我们需要添加以下代码:

let modules = import.meta.glob("../views/Pages/*.vue")

然后使用这个modules来配置组件:

// 错误示例:components:()=>import(`../views/Pages/${m.component}`)// 正确示例如下:component: modules[`../views/Pages/${m.component}`],

最终的pinia代码如下: 

 /src/store/index.ts:

import { defineStore } from 'pinia'import { RouteRecordRaw } from 'vue-router'let modules = import.meta.glob("../views/Pages/*.vue")// pinia状态管理器export const useStore = defineStore('myStore', { state: () => { return { // 路由表 routes: [] as Array<RouteRecordRaw> } }, getters: {}, actions: { // 添加动态路由,并同步到状态管理器中 addRoutes(data: Array<any>, router: any) { data.forEach(m => { this.routes.push({ path: m.path, name: m.name, // 错误示例:components:()=>import(`../views/Pages/${m.component}`) // 正确示例如下: component: modules[`../views/Pages/${m.component}`], }) }) this.routes.forEach(m => router.addRoute(m)) }, }})4.5、加载动态路由

配置了路由接口和加载路由的方法,接下来我们就需要加载我们的动态路由了。

思路也很简单,在我们的Home页面中调用路由的数据接口,在获取到数据之后调用加载的方法即可。为了验证我们的路由是否被加载成功,我们还需要添加三个路由对应的按钮,以便我们进行路由跳转。

/src/views/HomePage.vue:

<template> <h1>Home</h1> <div style="display: flex;gap:20px"> <button v-for="item in routes" @click="handleClick(item.path)"> {{ item.name }}</button> </div></template><script lang="ts" setup>import { useStore } from "../store";import { TestApi, GetDynamicRoutes } from '../apis'import { useRouter } from 'vue-router'import { computed } from "@vue/reactivity";import { onMounted } from "vue";const router = useRouter()const store = useStore()// 动态路由表const routes = computed(() => store.routes)// 路由按钮点击事件const handleClick = (path: string) => { router.push({ path })}onMounted(() => { if (store.routes.length < 1) { // 获取动态路由 GetDynamicRoutes().then(res => { store.addRoutes(res.data.data, router) }) } // 测试接口 TestApi().then(res => console.log(res.data)).catch(err => console.log(err))})</script>

效果如下: 

随便点击一个按钮,我们就能成功跳转到我们的动态路由了。

4.6、配置路由守卫

到这里,我们的动态路由已经加载成功了。不过其实我们还没有做完,这个动态路由还存在一个bug,假如我们刷新跳转后的页面,或者直接使用动态路由的路径进行跳转,就会出现以下情况:

可以看到,这种情况下我们的动态路由失效了,页面没了。这是因为我们的路由和pinia在刷新之后都会被重置,而我们加载路由的方法是在Home页面被调用的,当我们直接跳转到动态加载出来的路径或者直接在这个路径刷新的时候,Home页面并没有被加载,也就是说我们的动态路由并没有被加载上去,自然这个动态的页面也就丢失了。

解决方法有很多,举个例子,既然我们刷新丢了路由是因为Home页面没被加载,那我们把加载的方法直接写到必然会被调用的App.vue就可以了,这是个简单直接的方法。不过考虑到实际使用的时候,我们可能需要在路由跳转时进行鉴权操作,下面介绍另一种方法,使用路由守卫进行加载。

其实路由守卫加载的思路也很简单,假如我们的页面请求路径不是某个指定的路径的时候,我们就在跳转之前先去查询状态管理器中是否存在我们的动态路由,或者该动态路由是否满足我们的跳转要求,如果不满足就请求接口并加载我们的动态路由,并在加载完成后再继续跳转操作。在本项目中,我们的固定页面是Home页面,所以只要我们跳转的不是Home页面,就查询pinia是否存在路由表,如果没有则请求接口获取路由并加载。代码示例如下:

/src/router/index.ts:

import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router'import { useStore } from "../store";import { GetDynamicRoutes } from '../apis'// 静态路由表const routes: Array<RouteRecordRaw> = [ { // 路由重定向配置 path: '/', redirect: '/Home' }, { path: '/Home', component: () => import('../views/HomePage.vue') }]// 路由对象const router = createRouter({ history: createWebHistory(), routes})// 路由守卫router.beforeEach((to, from, next) => { if (to.path !== '/Home' && to.path !== '/') { const store = useStore() if (store.routes.length < 1) { GetDynamicRoutes().then(res => { store.addRoutes(res.data.data, router) next({ path: to.path, replace: true }) }).catch(_ => { next() }) } else { next() } } else { next() }})export default router

现在我们直接访问我们的动态页面也能成功加载了。

虽然能成功加载了,但是开发者工具那里还有一条报错:

[Vue Router warn]: No match found for location with path "/PageOne"

这是因为我们在路由跳转之前请求了一次接口进行加载,但是在完成路由加载之前,vue-router就直接先去找了这个路径,我们的路由都还没加载完成,当然也就找不到了,所以就会出这个警告。其实这个警告完全可以无视,不过我们最好还是处理一下,避免出现意外情况。

解决方法也很简单,添加一个404页面就可以了。在views文件夹中添加一个Error文件夹,并在此文件夹中添加404.vue文件。

<template> <h1>404</h1></template>

然后在静态路由中添加一个错误的路由:

 /src/router/index.ts:

import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router'import { useStore } from "../store";import { GetDynamicRoutes } from '../apis'// 静态路由表const routes: Array<RouteRecordRaw> = [ { // 路由重定向配置 path: '/', redirect: '/Home' }, { path: '/Home', component: () => import('../views/HomePage.vue') }, { // 404页面配置 path: '/:catchAll(.*)', component: () => import('../views/Errors/404.vue') }]// 路由对象const router = createRouter({ history: createWebHistory(), routes})// 路由守卫router.beforeEach((to, from, next) => { if (to.path !== '/Home' && to.path !== '/') { const store = useStore() if (store.routes.length < 1) { GetDynamicRoutes().then(res => { store.addRoutes(res.data.data, router) next({ path: to.path, replace: true }) }).catch(_ => { next() }) } else { next() } } else { next() }})export default router

 效果如下:

五、结尾

至此我们的动态路由就完成了,动态路由的实现方法有很多,本文介绍的也只是其中一种,也有很大的优化空间,这个就看需要参照实际需求了。

本文链接地址:https://www.jiuchutong.com/zhishi/299926.html 转载请保留说明!

上一篇:HTML【前端基础】(html前端技术)

下一篇:文本检测之DBNet,DBNet++(文本检测工具)

  • 淘宝交易记录怎么删除(淘宝交易记录怎么查支付记录)

    淘宝交易记录怎么删除(淘宝交易记录怎么查支付记录)

  • 淘宝不降权是什么意思(淘宝不降权是什么)

    淘宝不降权是什么意思(淘宝不降权是什么)

  • k歌出现铁粉榜是啥意思(全民k歌铁粉榜记录什么时候失效)

    k歌出现铁粉榜是啥意思(全民k歌铁粉榜记录什么时候失效)

  • 微信收藏的链接怎么发朋友圈(微信收藏的链接如何导出手机)

    微信收藏的链接怎么发朋友圈(微信收藏的链接如何导出手机)

  • 5000毫安电池的手机有哪些(5000毫安电池的手机哪款最好)

    5000毫安电池的手机有哪些(5000毫安电池的手机哪款最好)

  • 默认移动数据切换不了怎么办(默认移动数据切换不了)

    默认移动数据切换不了怎么办(默认移动数据切换不了)

  • 为什么微信分身用不了了(为什么微信分身登不上去别的app)

    为什么微信分身用不了了(为什么微信分身登不上去别的app)

  • 华为手机怎么退出正在运行的程序(华为手机怎么退出talkback程序)

    华为手机怎么退出正在运行的程序(华为手机怎么退出talkback程序)

  • 不贴钢化膜对手机屏幕有影响吗(不贴钢化膜对手机触控有影响吗)

    不贴钢化膜对手机屏幕有影响吗(不贴钢化膜对手机触控有影响吗)

  • 苹果手机复制不了文字怎么回事(苹果手机复制不到mac)

    苹果手机复制不了文字怎么回事(苹果手机复制不到mac)

  • 腾讯会议断开音频会被发现吗(腾讯会议断开音频会开麦吗)

    腾讯会议断开音频会被发现吗(腾讯会议断开音频会开麦吗)

  • 切换用户快捷键是什么(windows11切换用户快捷键)

    切换用户快捷键是什么(windows11切换用户快捷键)

  • 苹果手机无指纹什么意思(苹果手机无指纹是什么意思)

    苹果手机无指纹什么意思(苹果手机无指纹是什么意思)

  • 手机怎么截屏发送(手机怎么截屏发给朋友)

    手机怎么截屏发送(手机怎么截屏发给朋友)

  • 笔记本卡槽有什么用(笔记本上的卡槽是插什么卡的)

    笔记本卡槽有什么用(笔记本上的卡槽是插什么卡的)

  • 拼多多取代码在那(拼多多的代取码在哪里找)

    拼多多取代码在那(拼多多的代取码在哪里找)

  • 手机qq空间怎么清空说说(手机qq空间怎么显示手机型号)

    手机qq空间怎么清空说说(手机qq空间怎么显示手机型号)

  • 流量1x什么意思(流量是1x怎么办)

    流量1x什么意思(流量是1x怎么办)

  • 抖音私聊删除了别人能看到吗(抖音私聊删除了怎么恢复)

    抖音私聊删除了别人能看到吗(抖音私聊删除了怎么恢复)

  • 微信被冻结怎么办(微信被冻结怎么注销)

    微信被冻结怎么办(微信被冻结怎么注销)

  • beats solo3和studio3的区别(beats solo3和studio3哪个贵)

    beats solo3和studio3的区别(beats solo3和studio3哪个贵)

  • mate8找不到指纹设置(华为手机mate8指纹管理不见了怎么办)

    mate8找不到指纹设置(华为手机mate8指纹管理不见了怎么办)

  • 付费时无法连接itunes(付费时无法连接苹果服务器怎么办)

    付费时无法连接itunes(付费时无法连接苹果服务器怎么办)

  • 关闭电脑不用的端口该怎么做?(电脑不用的情况下怎么让它关闭屏幕)

    关闭电脑不用的端口该怎么做?(电脑不用的情况下怎么让它关闭屏幕)

  • 成本结算怎么处理?
  • 什么是原始凭证?审核原始凭证主要审查哪些内容?
  • 废铁回收行业前景怎么样
  • 2019发票认证期限新规
  • 资产负债表的期初余额是年初余额吗
  • 信用减值损失可以并入哪个科目
  • 工会经费计税基数包含支付职工的辞退福利
  • 注册资金印花税减半政策
  • 买二手房为什么要交个人所得税
  • 合同一方按手印另一方没按有效吗
  • 提供应税服务的企业
  • 税收抵免与税收的区别
  • 外购动力的分录
  • 低值易耗品怎么报废
  • 专票已认证但又没有发票
  • 费用一定计入当期损益吗
  • 2020年小规模生活服务业优惠政策
  • 财务人员必备知识
  • 收到的劳务费发票可以抵扣吗
  • 自建商品房转为自用增值税
  • ibm笔记本进bios
  • 老板拿的手机
  • 设置ahci模式后,开不了机
  • win11键盘全部没反应
  • 明细账是什么样子
  • 企业所得税必须要季度缴纳吗
  • 目标检测算法有哪些
  • stat命令的作用
  • 累计预扣法的适用条件
  • 财政补助结转和财政补助结余
  • 固定资金是什么科目
  • 现代服务增值税纳税义务发生时间
  • 摊销结束后
  • sql server中数据文件的扩展名是
  • 瓶盖再来一次表情包
  • 农产品购进时的会计分录
  • 外贸企业出口退税会计分录怎么做
  • 印花税购销合同改为买卖合同
  • 融资租入的固定资产视为自有固定资产
  • 法人股东的分红怎么算
  • 一般纳税人认定书是什么样子
  • 建筑企业的安全生产许可证由谁颁发
  • 企业购进生产用品税率
  • 增资减资改变股东要交税吗
  • 兼职员工对公司的好处
  • 进销存怎么看
  • 机械租赁公司需要什么证件
  • 在会计中,结转材料实际采购成本时什么意思
  • 未开票收入如何纳税申报
  • 培训发票能抵扣吗
  • 金税盘的初始密码一般是多少
  • 小规模纳税人哪里可以查
  • 出租车费用分录
  • 固定资产原价的含义
  • 子公司的亏损能算到母公司吗
  • 变更公司名称后银行如何做
  • 权益性投资包括哪些
  • 建账的大体流程有哪些
  • 探讨探讨
  • 存储过程sql server
  • win10怎么预览文件
  • 简单易上手 固态硬盘SSD安装WIN7系统的3种办法
  • linux lsof命令详解
  • win7电脑剪贴板里面的内容在哪打开
  • ghost7sp1安装教程
  • win8文件夹选项在哪
  • windows10version20h2的03
  • cocos2dx 3.0 quick lua schedler
  • c#怎么使用opencv
  • 批量创建用户
  • JavaScript中的数据类型
  • unity3d入门视频教程
  • xml-js
  • javascript规范
  • javascript设计简单计算机
  • javascript !
  • 改税务报表会有限风险吗
  • 贵阳北控水务电话客服电话
  • 河北保定地税局官网
  • 我国个人所得税起征点
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设