Vue 使用 vue-router 时,多级嵌套路由缓存问题处理

Vue 使用 vue-router 时,多级嵌套路由缓存问题处理

对于三级菜单(或多级嵌套路由),vue 都是 通过 keep-alive 组件来实现路由组件的缓存。

有时候三级或者多级路由时,会出现失效情况。以下是三级菜单缓存的例子。

最后会有惊喜!

1.配置嵌套路由

在 vue-router 中,嵌套路由需要正确配置 children 属性,并且每个路由组件都需要有唯一的 name,很重要。很重要。很重要。。

const routes = [
  {
    path: '/',
    component: Layout, // 布局组件
    children: [
      {
        path: '/menu1/path/',
        component: Menu1, // 一级菜单
        children: [
          {
            path: '/submenu1/path',
            component: SubMenu1, // 二级菜单
            children: [
              {
                path: 'item1',
                component: Item1, // 三级菜单
                name: 'Item1', // 确保每个组件有唯一的 name
                meta: {
                   noCache: false,   //自定义参数,是否缓存
                }
              },
              {
                path: 'item2',
                component: Item2,
                name: 'Item2',
                meta: {
                   noCache: false,
                }
              },
            ],
          },
        ],
      },
    ],
  },
];

2. 在嵌套路由中使用 router-view

在每一级菜单的组件中,都需要使用 router-view 来渲染子路由,记住是每一级

Menu1.vue

<template>
  <div>
    <h2>Menu 1</h2>
     <keep-alive>
         <router-view></router-view> <!-- 渲染二级菜单 -->
     </keep-alive>
  </div>
</template>

SubMenu1

<template>
  <div>
    <h3>SubMenu 1</h3>
    <keep-alive>
       <router-view></router-view> <!-- 渲染三级菜单 -->
    </keep-alive>
  </div>
</template>

3. 使用 keep-alive 缓存嵌套路由

在顶级组件(如 Layout.vue)中,用 包裹 ,确保所有嵌套路由组件都能被缓存。
如果只想缓存特定的嵌套路由组件,可以通过 includeexclude 属性来实现。

Layout.vue

<template>
  <div>
    <nav>
      <!-- 菜单导航 -->
      <router-link to="/menu1/submenu1/item1">Item 1</router-link>
      <router-link to="/menu1/submenu1/item2">Item 2</router-link>
    </nav>

    <!-- 使用 keep-alive 缓存所有嵌套路由 -->
    <keep-alive :include="cachedViews"  :exclude="notCacheName">
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: "clientManager",
  computed: {
    cachedViews() {
      return [...this.$store.state.tagsView.cachedViews];
    },
    key() {
      return this.$route.path;
    },
    notCacheName() {
      return [
        this.$route.meta && this.$route.meta.noCache ? this.$route.name : "",
      ];
    },
  },
};
</script>

此处有疑问点:

我查到的文档,基本上都是说在 顶级组件 Layout.vue 里面配置 keep-alive即可,下级的不用配置。

但是经过我测试,发现每一级都要配置 keep-alive,请看第二步。不配置的话,缓存就是不起作用。不知道为啥?

我是配置了每一级的,然后就可以了。此次请大家帮我解一下疑惑,万分感谢!

4. 最后的页面

<template>
  <div>
    <h4>Item 1</h4>
    <p>This is Item 1.</p>
  </div>
</template>

<script>
export default {
  name: 'Item1',
  activated() {
    console.log('Item1 被激活');
  },
  deactivated() {
    console.log('Item1 被停用');
  },
};
</script>

菜单缓存失败的原因

  • 路由配置不正确,导致组件被重复渲染。
  • 组件没有唯一的 name。
  • 嵌套路由的 没有正确渲染
  • 确认页面的 name 是否和 路由配置定义页面的 name 是否相同,不同肯定失败

最易出错的是最后一点,请仔细检查。

### 解决Vue-Router 3 刷新页面后路由丢失 当使用 Vue Router 3 构建单页应用程序 (SPA) 并遇到刷新页面后路由丢失的问题,这通常是因为浏览器刷新操作使得整个应用被重新加载,从而导致动态添加的路由信息丢失。为了防止这种情况发生并保持用户体验的一致性,有几种方法可以解决问题。 #### 方法一:采用 History Mode 配合 URL 重写工具 如果项目中使用的是 history 模式的路由,则需要服务器端支持 URL 重定向功能来处理未匹配到静态资源请求的情况。通过配置 Webpack 或其他构建工具中的 HTML 插件以及设置 Nginx 或 Apache 等 web server 来确保所有未知路径都被导向至 index.html 文件[^4]。 对于开发环境下的本地调试,可以通过修改 devServer 的配置项实现自动转发: ```javascript // vue.config.js module.exports = { publicPath: './', devServer: { historyApiFallback: true, } }; ``` #### 方法二:持久化存储 Route State 另一种解决方案是在每次成功导航之后将当前访问过的路由记录下来,并保存在一个可靠的介质里比如 localStorage 或 sessionStorage 中;当用户再次进入网站或是触发 F5 键刷新的候读取这些缓存的数据来进行初始化工作[^2]。 具体做法如下所示: 1. 创建一个新的 Vuex store module 用于管理 route state; 2.router.beforeEach() 全局前置守卫里面监听每一次成功的跳转事件并将最新的 location 对象序列化成字符串形式存入 local/sessionStorage; 3. 应用启动之初尝试从 storage 取出之前存在的状态对象并通过 replace 方法更新内部历史栈而不会引起视图变化。 这种方法虽然有效但也存在局限性——它依赖于客户端浏览器特性并且可能带来一定的性能开销。 #### 方法三:利用 keep-alive 组件优化体验 针对某些特定场景下(如多级嵌套路由),即使解决了上述问题仍然可能出现子组件销毁重建的现象影响交互流畅度。此可考虑引入 `<keep-alive>` 标签包裹住要缓存的内容部分以减少不必要的渲染过程提高效率[^1]。 ```html <template> <div id="app"> <!-- 缓存多个命名视图 --> <keep-alive :include="['child-a', 'child-b']"> <router-view></router-view> </keep-alive> </div> </template> <script> export default { computed: { cachedViews() { return this.$store.state.tagsView.cachedViews; }, }, }; </script> ``` 以上三种策略可以根据实际需求组合运用,既能够很好地应对由于页面刷新带来的各种挑战又兼顾到了不同层次上的优化考量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值