vue3动态路由刷新后空白或者404问题的解决
作者:梧桐凰 发布时间:2023-07-02 16:58:39
前言
之前用vue+ant-design-vue写了一个动态路由的页面,更新看一下不能用了555~~~
之前用的组件版本不知道了,回退也不知道哪个版本合适,就是用"vue": "^3.2.13" , "vue-router": "^4.0.3","vuex": "^4.0.0",ant-design-vue": "^3.2.5"重新写一个吧。
本文章是看了其它杂七杂八的博客,自己排错后编写下,不容易啊
实现
1.首先在store\index.js文件编写
import { createStore } from 'vuex'
export default createStore({
state: {
menu_lists: [] //菜单
},
getters: {
account(state) {
return state.menu_lists // 读取菜单列表
}
},
mutations: {
// 增加菜单
menuAdd(state, n) {
if (state.menu_lists.length == 0) {
state.menu_lists.push(n)
} else {
if (state.menu_lists.some(menu => menu.name != n.name)) {
state.menu_lists.push(n)
}
}
},
// 清空菜单
menuDelect(state) {
state.menu_lists.length = 0
}
},
actions: {
menu_add({ commit }, data) {
commit('menuAdd', data)
},
// 登出时调用将菜单数据删除
menu_delect({ commit }) {
commit('menuDelect')
}
},
modules: {
}
})
2.接着在App.vue编写
原因: 刷新时,动态路由需要重新挂载到路由实例, 但是在App.vue中调用init方法去初始化,并不能解决,因为App.vue属于路由的根,还未进入就被通配符拦截到404页面了, 我就在根上退出时将菜单保存在sessionStorage
// 创建完毕状态
created() {
//在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem("store")) {
this.$store.replaceState(
Object.assign(
{},
this.$store.state,
JSON.parse(sessionStorage.getItem("store"))
)
);
}
//在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload", () => {
sessionStorage.removeItem("store");
sessionStorage.setItem("store", JSON.stringify(this.$store.state));
});
}
3.读取后端菜单文件进行处理下
根据实际修改
vueRouter4中移除了addRouters,所以只能通过addRouter进行路由的动态添加
import { useRouter } from "vue-router";
import { useStore } from "vuex";
export default defineComponent({
setup() {
const store = useStore();
const router = useRouter();
// 路由数据重新封装
function routerPackag(routers) {
let accessedRouters = routers.filter((itemRouter) => {
if (itemRouter.component != "Layout") {
//处理组件---重点
router.addRoute("base", {
path: `/${itemRouter.path}`,
name: itemRouter.name,
component: () => import(`@/${itemRouter.component}`),
});
// 通过sessionStorage排查菜单是否存储,避免刷新后重复添加
if (!sessionStorage.getItem("store")) {
store.dispatch("menu_add", itemRouter);
}
}
//存在子集
if (itemRouter.children && itemRouter.children.length) {
routerPackag(itemRouter.children);
}
return true;
});
return accessedRouters;
}
}
)}
4.主要的来了,可以main或者router\index编写(我是在router\index编写的)
1、刷新404:将匹配全部为定义路径到404的路由从静态路由表中去除,在动态权限路由都添加了之后在添加。
2、刷新白屏:如果是在路由守卫router.beforeEach中检测并用router.addRoute添加的路由,则需要将动态权限路由添加后的next()放行,改为next({ path: ${to.path} })触发新导航。
import { createRouter, createWebHashHistory } from 'vue-router'
import store from "../store";
import { ref } from 'vue'
const routes = [
{
path: '/login',
name: 'login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( /* webpackChunkName: "Login" */ '../views/ant_login.vue'),
meta: {
requireAuth: false,
},
},
{
path: '/',
name: 'base',
component: () => import( /* webpackChunkName: "Login" */ '../views/ant_base.vue'),
meta: {
requireAuth: true,
},
children: [
{
path: 'index',
name: 'home',
redirect: "/map",
component: () => import( /* webpackChunkName: "Login" */ '../views/ant_home.vue'),
}
]
},
{
name: "NotFont",
path: '/:pathMatch(.*)*',
component: () => import('../components/NotFont.vue'),
alias: '/404', // 别名
hideMenu: true
}
]
const router = createRouter({
history: createWebHashHistory(), //createWebHashHistory是hash模式
// 页面刷新白屏问题
// mode取值说明:
// histroy:URL就像正常的 url,示例:http://localhost:8080/home
// hash:默认值,会多一个“#”,示例:http://localhost:8080/#/home
// abstract”:url不变示例:http://localhost:8080
// mode: 'history',
base: process.env.BASE_URL,
routes
})
// 下面全局前置路由守卫可在main文件编写
const registerRouteFresh = ref(true) // 定义标识,记录路由是否添加
router.beforeEach(async (to, from, next) => {
if (registerRouteFresh.value && store.state.menu_lists.length > 0) {
router.removeRoute("NotFont")
await store.state.menu_lists.forEach(e => {
//
// 处理组件---重点
router.addRoute("base", {
path: `/${e.path}`,
name: e.name,
component: () => import(`@/${e.component}`),
});
})
registerRouteFresh.value = false
// next({ ...to, replace: true })
next({
path: `${to.path}`
})
} else {
router.addRoute(router.options.routes[2])
next()
}
})
// 全局后置钩子-常用于结束动画等
router.afterEach(() => {
//不接受next
});
export default router
登出页面需要清除缓存
import { useStore } from "vuex";
export default defineComponent({
setup() {
const store = useStore()
function Logout() {
// 将vuex的菜单数据删除
store.dispatch("menu_delect");
window.sessionStorage.clear()
}
)}
排错过程
心累不说看了那些博客了真是大海捞个针,博客太杂了,有的写的next({ …to, replace: true })我就想知道你是咋成功的,哎,排的有好的但不实用,排到垃圾就跟不想说了,连使用的组件都没有就光把一段代码粘贴上去,累累累😫
来源:https://blog.csdn.net/weixin_43613890/article/details/125320428
猜你喜欢
- 本文代码重点在于演示Python扩展库matplotlib.pyplot中fill_between()函数的用法。import numpy
- 树莓派与arduino串口通信第一步:先设置硬件串口分配给GPIO串口输入sudo raspi-config命令进入树莓派系统配置界面,选择
- 1、调用字符映射表输入特殊符号在键盘上按win+R,在打开的对话框中输入“charmap”,会出现字符映射表:2、利用字符编码输入特殊符号#
- 秉承MVC架构的思想,CI中的所有控制器都需要经过单点入口文件index.php(默认)来加载调用。也就是说,在默认情况下,所有CI开发项目
- Python socket C/S结构的聊天室应用服务端:#!/usr/bin/env python#coding:utf8 import
- 本文实例讲述了python中__slots__的用法。分享给大家供大家参考。具体分析如下:定义__slots__ 后,可以再实例上分配的属性
- 先直接上代码r := gin.Default()// 注册中间件,使body可以重复读取r.Use(func(context *gin.Co
- 问题:生产环境的数据库可能比较大,如果直接进行全备而不压缩的话,备份集就会占用了大量磁盘空间。给备份文件的存放管理带来不便。解决方案:通过w
- 看着自己少得可怜的访问量,突然有一个想用爬虫刷访问量的想法,主要也是抱着尝试的心态,学习学习。其实市面上有一些软件可以代刷流量 比如 流量精
- 阅读上一节:美化段落文本 Ⅰweb标准知识——美化段落文本 Ⅱ懒,可能是唯一解释为什么这么长时间才写这一篇的主要原因。不述详情,以此责心。上
- 数据库是应用开发中必须要掌握的技巧,通常在数据库开发过程中,会有两种不同的方式:直接使用SQL语句,这种方式下,直接编写SQL,简单直观,但
- 一:代码实现class TreeNode: """节点类""&q
- 原始生成对抗网络Generative Adversarial Networks GAN包含生成器Generator和判别器Discrimin
- MyISAM 是MySQL中默认的存储引擎,一般来说不是有太多人关心这个东西。决定使用什么样的存储引擎是一个很tricky的事情,但是还是值
- Numpy 是Python科学计算的一个核心模块。它提供了非常高效的数组对象,以及用于处理这些数组对象的工具。一个Numpy数组由许多值组成
- 什么是RSS?RSS是站点用来和其他站点之间共享内容的一种简易方式(也叫聚合内容),通常被用于新闻和其他按顺序排列的网站,例如Blog。一段
- 将视频中的音频分离出来简单介绍使用python将音频从视频当中分离出来,形成一个mp3格式的音乐。使用环境和模块1.python 3.72.
- fetchone() 返回单个的元组,也就是一条记录(row),如果没有结果 则返回 Nonefetchall() 返回多个元组,即返回多个
- tempfile.TemporaryFile如何你的应用程序需要一个临时文件来存储数据,但不需要同其他程序共享,那么用TemporaryFi
- <SCRIPT language=JavaScript> <!-- var layerTo