网络编程
位置:首页>> 网络编程>> JavaScript>> vue3动态路由刷新后空白或者404问题的解决

vue3动态路由刷新后空白或者404问题的解决

作者:梧桐凰  发布时间:2023-07-02 16:58:39 

标签:vue3,空白,404

前言

之前用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

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com