Vue3动态路由(Vite+Vue3+TS+Mock)

这篇具有很好参考价值的文章主要介绍了Vue3动态路由(Vite+Vue3+TS+Mock)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、动态路由简介

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

参考示例如下:

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

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

Code .

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

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router


三、项目初始化及静态路由配置 

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@2.9.8 -D

ps. 目前vite-plugin-mock最新版本修改了配置选项,而且直接运行可能会报错,暂时建议使用2.9.8或2.9.8以下的版本,等待作者修复后再使用新版本。若需要使用最新版本,请移步至该项目的Github仓库(https://github.com/vbenjs/vite-plugin-mock),Issues中有解决报错的办法。

3.2、创建需要的文件夹以及文件

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

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

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

 vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

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 router

3.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 mock

3.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 World
export 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.ts

import { 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

运行结果如下所示:

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

从右侧开发者工具中可以看出,我们模拟的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文件夹中创建这三个页面。 

 vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

页面仅由一个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更加强大。

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

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

npm i pinia -S

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

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

 /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)

// 启用pinia
app.use(pinia)

app.mount('#app')

4.3、添加路由数据接口

/src/apis/index.ts

import req from '../utils/request'

/**
 * 测试接口
 */

// 测试用Hello World
export 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>

效果如下: 

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

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

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

4.6、配置路由守卫

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

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router

可以看到,这种情况下我们的动态路由失效了,页面没了。这是因为我们的路由和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

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

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-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

 效果如下:

vue3动态路由,Vue,vue.js,前端,typescript,vite,vue-router


五、结尾

至此我们的动态路由就完成了,动态路由的实现方法有很多,本文介绍的也只是其中一种,也有很大的优化空间,这个就看需要参照实际需求了。文章来源地址https://www.toymoban.com/news/detail-782769.html

到了这里,关于Vue3动态路由(Vite+Vue3+TS+Mock)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章 —— 第十一章 基础界面开发 (组件封装和使用)

    Vue 是前端开发中非常常见的一种框架,它的易用性和灵活性使得它成为了很多开发者的首选。而在 Vue2 版本中,组件的开发也变得非常简单,但随着 Vue3 版本的发布,组件开发有了更多的特性和优化,为我们的业务开发带来了更多便利。本文将介绍如何使用 Vue3 开发业务组件

    2024年02月19日
    浏览(89)
  • 前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章 —— 第十二章 常用工具函数 (Utils配置)

    在项目开发中,我们经常会使用一些工具函数,也经常会用到例如 loadsh 等工具库,但是这些工具库的体积往往比较大,如果项目本身已经引入了这些工具库,那么我们就没有必要再引入一次,所以我们需要自己封装一些工具函数,来简化我们的开发。 在 src/utils 目录下创建

    2024年02月20日
    浏览(62)
  • 【Vue H5项目实战】从0到1的自助点餐系统—— 搭建脚手架(Vue3.2 + Vite + TS + Vant + Pinia + Node.js)

    H5 项目基于 Web 技术,可以在智能手机、平板电脑等移动设备上的浏览器中运行,无需下载和安装任何应用程序,且H5 项目的代码和资源可以集中在服务器端进行管理,只需更新服务器上的代码,即可让所有顾客访问到最新的系统版本。 本系列将以肯德基自助点餐页面为模板

    2024年02月13日
    浏览(65)
  • vue3 vite ts引入vue文件报错 ts(2307)

    vue3 vite ts 生成的项目模板,在ts文件中引入vue文件报错 ts(2307),只是ts报错,并不影响项目运行。 官方文档有说明:http://vue.dragonlm.com/guide/typescript/overview.html#ide-support 解决方法是安装插件,之后即可正常解析路径,并可以跳转到对应文件。 TypeScript Vue Plugin (Volar)

    2024年02月16日
    浏览(57)
  • vue3+ts+vite项目引入echarts,vue3项目echarts组件封装

    技术栈 :Vue3 + Ts + Vite + Echarts 简介 : 图文详解,教你如何在 Vue3 项目中 引入Echarts , 封装Echarts组件 ,并实现常用Echarts图例 1.1 静态效果 1.2 动态效果 2.1 安装 Echarts npm: pnpm: 2.2 main.ts 中引入 2.3 Echarts 组件封装 /src/components/ReEcharts/index.vue 文件中写入如下代码 3.1 柱状图 实现

    2024年02月09日
    浏览(64)
  • 3d环形图开发(vue3+vite+ts)

    开发效果(待完善):   技术支持: Echarts  echarts-gl 安装: 注:echarts与echarts-gl版本需对应,可参考官网 pnpm add echarts@4.9.0 echarts-gl@1.1.2  组件封装:

    2024年02月07日
    浏览(48)
  • vite vue3项目打包,跳过ts检查

    遇到这个问题是因为vue文件中script标签没有写lang造成的  剩下的ts类型检查错误  \\\"build\\\": \\\"vue-tsc --noEmit --skipLibCheck vite build\\\",是因为这个vue-tsc打包对ts进行了类型检查,需要全部解决了才行,可以关闭,直接改成\\\"build\\\": \\\"vite build\\\",

    2024年02月16日
    浏览(60)
  • vue3+vite+ts+elementplus创建项目

    # vue3+vite+ts+pinia 学习笔记 ## 1、创建项目: npm init vite@latest     选择: vue、ts ## 2、进入项目目录后:npm install 安装 ## 3、运行项目: npm run dev ## 4、安装常用插件:     1、安装 npm install vue-router@latest 配置:在src目录下新建router目录,创建index.ts文件代码如下:       ```javascript 创建

    2024年02月09日
    浏览(61)
  • 【Vue3+Ts+Vite】配置滚动条样式

    2024年02月15日
    浏览(46)
  • 使用 Vite + Vue3 + Element-Plus + Pinia + Ts 搭建 Vue3 项目

    Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。 首先 npm 输入: Project name :项目名称 Select a framework :选择一个框架 Select a variant :选择 ts 或者 js 输入项目名称后选择 vue 选择

    2024年02月09日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包