位置: 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++(文本检测工具)

  • qq音乐一起听歌一个人有vip另一个人可以听吗(qq音乐一起听歌怎么用)

    qq音乐一起听歌一个人有vip另一个人可以听吗(qq音乐一起听歌怎么用)

  • applewatch7如何实时检测心跳

    applewatch7如何实时检测心跳

  • 付费问答社区是什么(付费问答社区相关数据)

    付费问答社区是什么(付费问答社区相关数据)

  • 耳机要转动线才有声音(耳机要转动线才能充电吗)

    耳机要转动线才有声音(耳机要转动线才能充电吗)

  • oppo findx上市时间(oppo findx多久出的)

    oppo findx上市时间(oppo findx多久出的)

  • 苹果xr卡屏关不了机(苹果xr卡屏不动也重启不了)

    苹果xr卡屏关不了机(苹果xr卡屏不动也重启不了)

  • 像素是分辨率吗(怎么调像素和分辨率)

    像素是分辨率吗(怎么调像素和分辨率)

  • qq找回密码出现error什么意思(qq找回密码出现网络异常或不稳定怎么解决)

    qq找回密码出现error什么意思(qq找回密码出现网络异常或不稳定怎么解决)

  • a58主板配什么cpu(a58主板配什么内存)

    a58主板配什么cpu(a58主板配什么内存)

  • 一个人最多能申请几个手机号(一个人最多能申请几张信用卡)

    一个人最多能申请几个手机号(一个人最多能申请几张信用卡)

  • 物联网是什么相连组成的网络(物联网是指什么和什么关联)

    物联网是什么相连组成的网络(物联网是指什么和什么关联)

  • 笔记本电脑鼠标没反应怎么回事(笔记本电脑鼠标触摸板没反应)

    笔记本电脑鼠标没反应怎么回事(笔记本电脑鼠标触摸板没反应)

  • 华为怎么呼叫转移到另一台手机(华为怎么呼叫转移)

    华为怎么呼叫转移到另一台手机(华为怎么呼叫转移)

  • oppofindx2和OPPOfindpro区别(oppofindx2和oppofindx5)

    oppofindx2和OPPOfindpro区别(oppofindx2和oppofindx5)

  • 小米8突然没信号了(小米突然没信号)

    小米8突然没信号了(小米突然没信号)

  • 荣耀手环支持什么手机(荣耀手环什么时候出7)

    荣耀手环支持什么手机(荣耀手环什么时候出7)

  • 一个手机号可以注册几个快手(一个手机号可以注册几个支付宝)

    一个手机号可以注册几个快手(一个手机号可以注册几个支付宝)

  • 新iphone8p充电充多久(新买的苹果8p充电慢是怎么回事)

    新iphone8p充电充多久(新买的苹果8p充电慢是怎么回事)

  • 怎样在word中加波浪线(怎样在word中加横线)

    怎样在word中加波浪线(怎样在word中加横线)

  • 卡暂停服务是什么意思(暂停服务以后手机卡怎么恢复)

    卡暂停服务是什么意思(暂停服务以后手机卡怎么恢复)

  • 为什么手机关屏后收不到微信提示(为什么手机关屏幕了别人打电话就不显示)

    为什么手机关屏后收不到微信提示(为什么手机关屏幕了别人打电话就不显示)

  • 魅族16T是双卡双待吗(魅族16双卡还是单卡)

    魅族16T是双卡双待吗(魅族16双卡还是单卡)

  • 爱奇艺怎么销号(爱奇艺怎么注销爱奇艺号)

    爱奇艺怎么销号(爱奇艺怎么注销爱奇艺号)

  • 手机怎样截百度地图(手机如何在百度上截图快捷键)

    手机怎样截百度地图(手机如何在百度上截图快捷键)

  • u盘泡水后快速处理的办法(u盘泡水里了还能用吗)

    u盘泡水后快速处理的办法(u盘泡水里了还能用吗)

  • u盘查到电脑无法读取(u盘插电脑上不显示)

    u盘查到电脑无法读取(u盘插电脑上不显示)

  • 苹果备忘录怎么命名(苹果备忘录怎么发送给微信好友)

    苹果备忘录怎么命名(苹果备忘录怎么发送给微信好友)

  • crrul20是什么型号(cr20是什么意思)

    crrul20是什么型号(cr20是什么意思)

  • excel如何启用宏(Excel如何启用宏?)

    excel如何启用宏(Excel如何启用宏?)

  • 微信视频太长发不出去怎么办(微信发视频太长了怎么办?)

    微信视频太长发不出去怎么办(微信发视频太长了怎么办?)

  • 企业收取培训费
  • 购买办公用品属于会计对象吗
  • 招聘只招一个人
  • 个人名字的发票专用章
  • 收据怎么粘贴在费用报销单上
  • 自产自用应税消费品的消费税,其纳税环节
  • 餐饮增值税发票抵扣
  • 个体营业执照从哪里查询
  • 已经认证的发票对方可以作废吗
  • 年报中资产总额和所有者权益都填0
  • 进口环节增值税是中央税还是地方税
  • 外购货物准予抵扣进项税额26万元,货物已验收入库
  • 注销时其他应付款余额怎么账务处理
  • 外币资产汇兑损益计算
  • 为安装设备所发生的差旅费入什么科目
  • 退货款现金流量表填经营活动的什么科目
  • 店铺不盈利还开吗
  • 领购增值税专用发票
  • 机动车销售发票如何补开?
  • 公司采购商品支付货款未开票会计分录
  • 会计准则规定
  • 折现率为10%怎么算折现系数是多少
  • 派发现金红利怎么知道有没有
  • 免税的普通发票怎么开
  • windows10更新怎么办
  • 允许企业所得税税前扣除的公益性捐赠的条件包括
  • linux获取网络设备的交换机网络
  • cpu天梯图2022最新版1240p
  • 腾讯地图js api
  • win10开机强制进入高级选项怎么退出
  • 增值税跟企业所得税的关系
  • 营改增预收款确认收入
  • 生产加工型企业安全隐患排查内容
  • 长期借款利息调整会计分录
  • 企业收到海河工厂发运的乙材料,并验收入库
  • 保险补偿金额的计算
  • web攻防之业务安全实战指南
  • php new
  • yolo目标识别
  • 综合所得个税计算例题
  • discuz设置门户
  • 生育津贴如何做帐
  • 营业收入的构成分析包括
  • sqlserver2008中有那些设备
  • access数据库如何
  • 人力资源行业税收优惠
  • 个体工商户还没开业也要报税吗
  • 差旅费报销会计分录题目
  • 旅行社开具的发票
  • 收入准则适用范围
  • 车户过户
  • 以汽车投资作为投资项目
  • 注册资本为0的公司可以去吗
  • 如何申请高新技术企业认定
  • centos7.6怎么安装
  • sqlserver日期范围
  • MySQL部署时提示Table mysql.plugin doesn’t exist的解决方法
  • Linux下mysql的root密码修改方法
  • win7资源管理器未响应怎么办
  • onenote for windows 10怎么用
  • 如何配置samba配置文件
  • linux的压缩包
  • sunasServ.exe - sunasServ是什么进程 有何作用
  • 进程 cmd
  • 如何在windows上打开蓝牙
  • windows xp.
  • windows7 运行
  • window7iis配置步骤
  • liunx改时间命令
  • unity3d协程的作用
  • bat批处理命令教程
  • Linux数据库备份的命令
  • javascript高级程序设计最新版
  • jquery+ajax+text文本框实现智能提示完整实例
  • python win
  • 从局部变量和全变量区分
  • 办理对外支付税务备案需要多久时间
  • 新入职税务干部工作心得
  • 动漫企业的增值税率
  • 重庆税务查询企业信息查询系统
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设