vue3 keep-alive缓存 多层嵌套路由 onMounted多次触发及根据不同情况可能需刷新缓存页面的问题

1. onMounted多次触发

原因

一级路由找不到路由对应的route.meta.keepAlive,导出在访问一级路由和子路由都触发生命周期加载

解决方案

在外层router-view的时候,判断获取的route层级,如果不是一级目录则通过当前route获取后再使用,接口调用不要写在onMounted,需要写到onActivated中

一级页面代码

<router-view v-slot="{ Component, route }">
            <keep-alive>
              <component
                :is="Component"
                :key="getFirstLevelRoute(route).name"
                v-if="getFirstLevelRoute(route).meta.keepAlive"
              ></component>
            </keep-alive>
            <component
              :is="Component"
              :key="getFirstLevelRoute(route).name"
              v-if="!getFirstLevelRoute(route).meta.keepAlive"
            ></component>
          </router-view>
const getFirstLevelRoute = route => {
  if (!Array.isArray(route.matched) || route.matched.length === 0) {
    return route;
  }
  return route.matched[0];
};

子页面代码(正常缓存写法即可)

  <router-view v-slot="{ Component, route }">
   <keep-alive>
      <component :is="Component" :key="route.name" v-if="route.meta.keepAlive"></component>
   </keep-alive>
   <component :is="Component" :key="route.name" v-if="!route.meta.keepAlive"></component>
</router-view>

2. 优化缓存后页面一直不刷新问题(部分逻辑需要刷新)

例如:从菜单进入缓存列表页面需要刷新,但是从列表页面进入详情页后返回不需要刷新列表页

思路:
1、在路由中新增isBack字段用于判断是否需要刷新, 路由守卫出判断从那个页面进入的,不需要刷新改为true(例如详情),特殊情况也可以在地址中添加isRefresh参数控制(isRefresh==1需要刷新),实现同一个页面可根据不同的情况拼接isRefresh参数实现是否需要刷新缓存
2、不加入sessionStorage缓存会导致从详情切换到任意缓存列表页都不会请求数据,改进后只有返回跳转前的缓存页才不请求数据

路由守卫代码

router.beforeEach((to, from, next) => {
	var prevRouter = [];
    if (sessionStorage.getItem("prevRouterList")) {
        try {
            prevRouter = JSON.parse(sessionStorage.getItem("prevRouterList") || '[]')
        } catch (e) {
        }
    }
    
	if (from.meta.isDetail && !from.query.isRefresh && prevRouter?.find(item=>item==to.path)) {
        to.meta.isBack = true;
    } else {
        to.meta.isBack = false
    }
    
  	var findIndex = prevRouter.findIndex(item => item == to.path);
    if (to.meta.keepAlive) {
        if (findIndex == -1) {
            prevRouter.push(to.path);
        }
    } else if (!to.meta.isDetail) {
        if (findIndex > -1) {
            prevRouter.splice(findIndex, 1);
        }
    }
    sessionStorage.setItem("prevRouterList", JSON.stringify(prevRouter));
    next()
})

页面路由

export default [
    {
        path: "/setting",
        name: "setting",
        meta: {
            transform: false,
        },
        children: [
            {
                path: "list",
                name: "list",
                meta: {
                    keepAlive: true
                },
                component: () => import("@/pages/app-settings/jiuchuang/notice-examine.vue")
            },
            
            {
                path: "detail",
                name: "detail",
                meta: {
                    isDetail: true
                },
                component: () => import("pages/app-settings/components/notice/notice-detail.vue")
            },
           
        ],
        component: () => import("pages/index.vue")
    },
]

列表页面代码

import { onActivated } from "vue";
onActivated(() => {
  // 调用时机为首次挂载以及每次从缓存中被重新插入时
  if (!route.meta.isBack) {
  	//获取列表数据
   	loadata()
  }
});
### Vue Router 使用问题及解决方案 #### 1. 安装和配置过程中出现问题 当尝试安装 `vue-router` 或者其插件如 `unplugin-vue-router` 时,可能会遇到依赖安装失败的情况。这通常是因为网络连接不稳定或者是版本兼容性问题所引起的[^4]。 对于此类情况的一个常见解决办法是: - 尝试更换 npm 的镜像源来加速下载速度; - 确认当前使用的 Node.js 和 Vue 版本与 `vue-router` 是否匹配; 如果仍然无法解决问题,则可以考虑查看官方文档中的最低支持环境要求以及社区论坛上的讨论寻找帮助。 #### 2. 页面刷新后丢失状态 在一个单页面应用(SPA)中使用 `vue-router` 后,在浏览器地址栏输入特定路径访问或者点击浏览器前进/回退按钮时,发现页面重新加载之后原本保存的状态消失了。这是因为每次刷新都会触发整个应用程序的重载过程,从而导致之前存储于内存里的数据被清除掉。 为了保持导航历史记录和其他临时性的用户交互信息不随页面刷新而消失,可以通过以下方式处理这个问题: - 利用前端本地储存技术(LocalStorage, SessionStorage)持久化重要参数; - 结合 Vuex 实现全局状态管理,并配合 keep-alive 组件缓存视图; ```javascript // 示例代码:利用 localStorage 存储 token 并在初始化时读取 const app = createApp(App); app.use(createRouter({ routes, })); if (localStorage.getItem(&#39;token&#39;)) { store.commit(&#39;setToken&#39;, JSON.parse(localStorage.getItem(&#39;token&#39;))); } ``` #### 3. 动态路由匹配模式下子级嵌套显示异常 有时开发者会遇到这样的场景:定义了一组带有通配符(`*`)或其他动态部分(:id)的父级路由规则,但在实际渲染过程中却发现预期应该作为子项呈现的内容并没有按照设想那样展示出来。造成这种现象的原因可能是由于未能正确设置父子关系或是忽略了必要的命名空间声明所致。 针对上述状况建议采取如下措施加以修正: - 明确指定各级别之间的层次结构关系; - 对于存在多层嵌套的情形要记得给定唯一的名称属性以便区分不同实例间的差异; ```html <!-- 正确做法 --> <template> <div id="app"> <!-- ...其他内容... --> <router-view></router-view> <!-- 主区域 --> <!-- 如果有更深层次的布局求可继续添加 --> <transition name="fade" mode="out-in"> <keep-alive :include="cachedViews"> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> </transition> <router-view v-else></router-view> </div> </template> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值