当前位置: 首页 > 知识库问答 >
问题:

vue.js - KeepAlive和携带key属性的RouteView同时使用,routerView初始没有匹配路由,手动跳转页面为什么渲染失败?

邓德厚
2024-12-23

页面首次加载,加载了一个包含<router-view/>标签的页面,且被keepAlive包裹,如下

//index.vue ,路由为/index
<div>刷新按钮</div>
<div>打开a页面</div>
<keep-alive>
  <router-view/>
</keep-alive>

此时<router-view>是没有渲染内容的,因为路由只匹配到当前页面层,但是在后续操作中,想通过刷新按钮,使得keepAlive包裹下的所有页面能手动刷新,所以我给router-view增加了key。
出现了一个新的问题,当想要打开a页面(路由/index/a)的时候,通过$router.push()方法去跳转时,总是无法渲染a页面,而再去点击菜单其他选项跳转页面的时候,是可以成功的。只有第一个页面总是无法渲染成功,请问是什么原因呢?

当去掉KeepAlive的时候,页面能够成功渲染。
我的路由配置

{
  path: '/index',
  name: 'index',
  component:() => import('@/pages/index/index'),
  children:[
    {
        path: "a",
        name: "a",
        component: () => import('@/pages/index/a')
    }
    ......
  ]
},

共有2个答案

汝和裕
2024-12-23

KeepAlive 和 key 属性的结合使用导致了 RouterView 的缓存行为与路由更新的不匹配。在首次加载 /index 页面时,KeepAlive 包裹的 RouterView 没有渲染内容(因为没有匹配到子路由),而当你通过 $router.push() 跳转到 /index/a 时,KeepAlive 的缓存机制可能无法正确处理子路由的变化

<div>
    <div @click="refresh">刷新按钮</div>
    <div @click="goToA">打开a页面</div>
    <keep-alive>
      <router-view :key="routerViewKey" />
    </keep-alive>
  </div>
 const routerViewKey = ref(route.fullPath)

加个key应该就好了吧

廉鸿运
2024-12-23

回答

问题出在 keep-alive 和动态路由(带有子路由的 router-view)的结合使用上。keep-alive 缓存了组件的状态,但在某些情况下,尤其是当路由路径变化而组件未正确销毁和重建时,可能会导致渲染问题。

原因分析

  1. 初始状态无匹配路由
    当页面首次加载 /index 时,<router-view/> 内没有匹配的子路由,因此没有渲染任何内容。此时 keep-alive 包裹了一个空的 router-view
  2. 动态添加 key 属性
    虽然你尝试通过添加 key 属性来强制组件重新渲染,但如果 key 值的变化没有正确触发组件的销毁和重建,keep-alive 仍然会保持之前的状态(即空状态)。
  3. 路由跳转问题
    当你通过 $router.push() 跳转到 /index/a 时,如果 keep-alive 缓存了之前空状态的 router-view,它可能不会正确地更新为新路由对应的组件。

解决方案

  1. 确保 key 变化有效
    确保每次路由变化时,key 属性都能有效变化。这可以通过监听路由变化并动态设置 key 来实现。例如:

    <template>
      <div>
        <div>刷新按钮</div>
        <div>打开a页面</div>
        <keep-alive :include="cachedViews">
          <router-view :key="routeKey"/>
        </keep-alive>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          routeKey: this.$route.fullPath, // 使用完整路径作为key
          cachedViews: ['index', 'a'] // 根据需要缓存的视图设置
        };
      },
      watch: {
        $route(to, from) {
          // 当路由变化时,更新key
          this.routeKey = to.fullPath;
        }
      }
    };
    </script>
  2. 条件渲染 router-view
    如果可能,考虑在路由有子路由时才渲染 router-view,这样可以避免 keep-alive 缓存一个空视图。
  3. 调整路由配置
    确保路由配置正确,并且所有需要的组件都已正确导入和注册。
  4. 使用 v-if 控制 keep-alive
    在某些情况下,使用 v-if 根据条件渲染 keep-aliverouter-view 可能更可靠:

    <template>
      <div>
        <div>刷新按钮</div>
        <div>打开a页面</div>
        <keep-alive v-if="hasChildRoute" :include="cachedViews">
          <router-view :key="routeKey"/>
        </keep-alive>
        <router-view v-else :key="routeKey"/>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          routeKey: this.$route.fullPath,
          cachedViews: ['index', 'a'],
          hasChildRoute: false
        };
      },
      watch: {
        $route(to) {
          this.routeKey = to.fullPath;
          this.hasChildRoute = to.matched.some(record => record.children && record.children.length);
        }
      },
      created() {
        this.hasChildRoute = this.$route.matched.some(record => record.children && record.children.length);
      }
    };
    </script>

通过这些方法,你可以更可靠地控制 keep-aliverouter-view 的行为,确保在路由变化时正确渲染组件。

 类似资料:
  • 我设置3个一级路由,然后想在这3个一级路由的子路由下渲染各自不同的404页面。404路径匹配不对 为什么我访问"/c/c2"路径时,匹配到的是B的404页面即 BNotFound,而不是 CNotFound。如何改正? AI 回答的不对,我用的是最新的 vue-router 版本 4.3.0。(我已经知道解决方法了,就在之前方式加点东西搞定各种情况下的不同404页面 ) 报错:vue-router

  • 问题描述 点击三级分类时会重定向到 home,这里不是重定向的问题(而是参数丢失的问题),因为我试过了,在 route.js 里把重定向的代码去掉后,页面会出现空白,路径变为 http://localhost:8080/#/ 问题出现的环境背景及自己尝试过哪些方法 跳转的路径没问题,如图,手动添加参数是能正常跳转的 使用 this.router.push 跳转前打印参数,发现也没问题,如图 相关代

  • 问题内容: 使用React的新效果挂钩,如果重新渲染之间某些值没有改变,我可以告诉React跳过应用效果-来自React文档的示例: 但是上面的示例将效果应用于初始渲染,以及随后在已更改的地方重新渲染。如何告诉React跳过初始渲染的效果? 问题答案: 如指南所述, 效果挂钩(useEffect)增加了从功能组件执行副作用的功能。它的作用与React类中的componentDidMount,com

  • 本文向大家介绍vue.js,ajax渲染页面的实例,包括了vue.js,ajax渲染页面的实例的使用技巧和注意事项,需要的朋友参考一下 关于上次说的用vue.js,zepto,node.js,webpack等技术重构CNode。这是一个比较入门的项目,一般你学完vue就可以上手了,CNode网站有公开的API所以你可以获取这个网站的所有数据接口,然后渲染到页面上,用CSS等加工一下就可以了。起初,

  • 我的页面是三级嵌套路由,结构类似于 /message/detail/0。 但当我使用 this.$router.push('/index') 返回首页的时候,页面路径变成了/message/detail/index。 请问我该如何解决这个问题,希望从 /message/detail/0 页面直接跳转到 /index。 这个是路由配置的JS:

  • vue3中使用keepAlive的include属性不生效 我想只缓存/template-allocation这个路由,但是没有生效。 想通过vue-devtools查找下组件的名称: 发现组件名字为Index,所以找到问题了

  • 前端页面渲染前向其他页面跳转,发生无限循环的问题。 代码如上: 问题背景是这样:我自己的一个云服务器网站还没有域名,只实现了前端的ssl认证,但是没有实现后端的ssl认证,导致前端无法向后端发送https请求。于是我目前打算,当用户通过https协议登录前端网站的时候,自动跳转到http协议下的该网站,具体实现的代码如上面所写,但是部署到云服务器并测试的时候发现网页不断弹出alert框,且一直在当