vite+vue3+pinia实现动态注册懒加载路由教程
更新时间:2025年04月28日 14:16:35 作者:Tt涛㏒
这篇文章主要介绍了vite+vue3+pinia实现动态注册懒加载路由教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
模块版本
- vite:^5.4.10
- vue:^3.5.12
- vue-router:^4.4.5
- pinia:^2.2.6
- pinia-plugin-persistedstate:^4.1.3(pinia持久化插件)
业务需求说明
每个程序都要满足不同的业务需求,以下代码只是满足我当前的业务需求
- 后端保存了每个用户的前端路由列表信息
- 前端默认路径为’/login’,比如www.xxxx.com访问默认显示login页面
- 前端默认注册静态路由’/login’,并重定向到路径’/’
- 用户点击登录后获取路由列表,通过addRoute注册路由
router代码
import {createRouter, createWebHistory} from 'vue-router'
import type {Router} from 'vue-router'
const router: Router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
component: () => import('@/views/Login.vue')
},
{
path: '/login',
name: 'login',
meta: {
navBar: false,
token: false
},
component: () => import('@/views/Login.vue')
}
],
})
export default routerLogin页面(ts+setup)
<script lang="ts" setup>
import {ref} from "vue"
import {useRouter} from 'vue-router'
import {loginApi} from '@/api/login/loginApi'
import {useUserInfo, useMyToken} from '@/stores/counter'
import type {RouterListItem} from '@/types/login'
const userInfo = useUserInfo()
const myToken = useMyToken()
const router = useRouter()
/** 用户输入账号 */
const userName = ref<string>('')
/** 用户输入的密码 */
const password = ref<string>('')
/** 登录API */
const logon = async () => {
/** 发送登录请求,携带用户账号和密码信息 */
loginApi(userName.value, password.value).then((res) => {
/** 后端返回的用户信息和路由列表,写入pinia */
userInfo.setUserInfo(res.result.info)
/** 用户token信息,写入pinia */
myToken.setMyToken(res.result.token)
/** 调取pinia内的方法注册路由 */
userInfo.registeredRoute()
/** 由于后端返回的路由列表是JSON格式,需要转换 */
let routerListArr: RouterListItem[] = []
if (userInfo.userInfo !== undefined) {
/** 转换路由信息 */
routerListArr = JSON.parse(userInfo.userInfo?.router_list)
}
/** 跳转到用户路由列表中的第一个路由 */
router.replace(routerListArr[0].path)
}, (err) => {
/** 错误提示 */
ElMessage({
message: err.response.data.message,
type: 'error'
})
})
}
</script>pinia代码
import {ref} from 'vue'
import {defineStore} from 'pinia'
import type {RouterListItem, UserInfo} from '@/types/login'
/** 导入的是自己的路由文件 src-router-index.ts */
import myRouter from '@/router/index'
/** 用户信息相关 */
export const useUserInfo = defineStore(
'userInfo',
() => {
/** 用户信息 */
const userInfo = ref<UserInfo | undefined>(undefined)
/** 存储用户信息方法 */
const setUserInfo = (info: UserInfo): void => {
userInfo.value = info
}
/** 清除用户信息方法-用于退出登录或token验证失败 */
const clearUserInfo = (): void => {
userInfo.value = undefined
}
/** 注册路由方法 */
const registeredRoute = () => {
/** 判断userInfo.value是否为undefined,不是则进入 */
if (userInfo.value !== undefined) {
/** 由于我的后端返回路由列表是JSON格式,需要转换后使用 */
const routerListArr: RouterListItem[] = JSON.parse(userInfo.value?.router_list)
/** 通过循环添加路由 */
for (const item of routerListArr) {
const route = {
path: item.path,
name: item.name,
meta: {
navBar: item.meta.navBar,
token: item.meta.token
},
/** 懒加载导入vue页面
由于我的后端返回的component名称是带有后缀名的,直接导入vite会报警告,虽然不影响使用,但是安全起见
还是替换了为好,这里使用replace将.vue替换为空
*/
component: () => import(`../views/${item.component.replace('.vue', '')}.vue`)
}
myRouter.addRoute(route)
}
}
}
return {
userInfo,
setUserInfo,
clearUserInfo,
registeredRoute
}
},
{
/** pinia持久化 */
persist: true
})
/** 用户token相关 */
export const useMyToken = defineStore(
'myToken',
() => {
/** token信息 */
const myToken = ref<string | undefined>(undefined)
/** 存储token信息方法 */
const setMyToken = (token: string) => {
myToken.value = token
}
/** 清除token信息方法-用于退出登录或token验证失败 */
const clearMyToken = () => {
myToken.value = undefined
}
return {
myToken,
setMyToken,
clearMyToken
}
},
{
/** pinia持久化 */
persist: true
})
关于替换.vue后缀的说明
导入必须以 或 开头。./…/
所有导入都必须相对于导入文件开始。导入不应以变量、绝对路径或裸导入开头:
// Not allowed
import(bar);
import(`${bar}.js`);
import(`/foo/${bar}.js`);
import(`some-library/${bar}.js`);导入必须以文件扩展名结尾
文件夹可能包含您不打算导入的文件。因此,我们要求导入在导入的静态部分中以文件扩展名结尾。
// Not allowed
import(`./foo/${bar}`);
// allowed
import(`./foo/${bar}.js`);导入到您自己的目录必须指定文件名模式
如果您导入自己的目录,则最终可能会得到您不打算导入的文件,包括您自己的模块。因此,需要提供更具体的文件名模式:
// not allowed
import(`./${foo}.js`);
// allowed
import(`./module-${foo}.js`);详细信息见文档:dynamic-import-vars#limitations
main代码(vue的main.ts文件内)
import './assets/main.css'
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
/** 导入createPinia用于创建pinia */
import {createPinia} from 'pinia'
/** 导入ElementPlus */
import ElementPlus from 'element-plus'
/** 导入ElementPlus国际化文件-中文 */
import zhCn from 'element-plus/es/locale/lang/zh-cn'
/** 导入pinia持久化插件 */
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
/** 导入pinia内的useUserInfo,用于动态注册路由 */
import {useUserInfo} from '@/stores/counter'
/** 导入el-loading样式 */
import 'element-plus/theme-chalk/el-loading.css'
/** 导入el-message样式 */
import 'element-plus/theme-chalk/el-message.css'
import type {Pinia} from 'pinia'
const app = createApp(App)
/** 创建pinia */
const pinia: Pinia = createPinia()
/** 注册piniaPluginPersistedstate持久化插件 */
pinia.use(piniaPluginPersistedstate)
/** 注册pinia */
app.use(pinia)
/** 获取pinia内的userInfo,用于动态注册路由 */
const userInfo = useUserInfo()
/** 动态注册路由,并且防止刷新页面导致路由丢失
这里直接调用userInfo.registeredRoute()会不生效,需要写到函数内部,再调用函数
并且需要写在app.use(router)之前
*/
const addRouter = () => {
userInfo.registeredRoute()
}
addRouter()
app.use(router)
/** 注册ElementPlus,并使用中文模式 */
app.use(ElementPlus, {
locale: zhCn,
})
app.mount('#app')总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
vue webpack build资源相对路径的问题及解决方法
这篇文章主要介绍了vue webpack build资源相对路径的问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-06-06
vue-cli脚手架build目录下utils.js工具配置文件详解
这篇文章主要介绍了vue-cli脚手架build目录下utils.js工具配置文件详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-09-09
利用vuex-persistedstate将vuex本地存储实现
这篇文章主要介绍了利用vuex-persistedstate将vuex本地存储的实现,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-04-04


最新评论