Vue 2 <keep-alive> 不能与 <router-view> 和密钥一起使用

Posted

技术标签:

【中文标题】Vue 2 <keep-alive> 不能与 <router-view> 和密钥一起使用【英文标题】:Vue 2 <keep-alive> not working with <router-view> and key 【发布时间】:2017-04-15 08:54:12 【问题描述】:

我正在使用带有一系列组件(如选项卡)的 vue-router。每个&lt;router-link&gt; 是一个选项卡,下面的空格是&lt;router-view&gt;。其中两个选项卡是具有不同过滤器的相同组件,假设它们是products,路由器添加了一个过滤参数:/products/new & /products/sale

products 内部是单独的 product 组件,这些组件会在路由打开时安装。我的问题是,当我在路由之间切换并更改过滤器参数时,product 组件每次都会重新安装。我想缓存它们,这样来回切换更容易。为此,我设置了&lt;keep-alive&gt; 并将:key='$route.fullPath' 添加到我的&lt;router-view&gt;,但它们似乎没有被缓存。当我在products 之间切换时,每个product 仍在触发mounted() 事件。

<keep-alive>
  <router-view :key='$route.fullPath'></router-view>
</keep-alive>

我是否应该将每个 products 视图变成一个单独的组件?

【问题讨论】:

试试这个答案,虽然这是 vue 2+:keep-alive and router-view 【参考方案1】:

要在路由器视图中使用keep-alive,您应该在视图路由器上使用唯一键,如下所示:

 <keep-alive>
   <router-view :key="$route.fullPath"></router-view> 
 </keep-alive>

不要忘记在保持活动状态时使用 max 属性来防止内存开销

<keep-alive max="5">

或者只包含想要缓存的组件:

<keep-alive include="FirstComp,SecondComp"> 

并且对于组件内的每个组件,如果您想要缓存,则需要保持它们处于活动状态

<keep-alive>
  <product></product>
</keep-alive>

【讨论】:

注意:&lt;keep-alive include="FirstComp,SecondComp"&gt; 仅适用于命名组件(具有 'name' 属性的组件)。【参考方案2】:

Vue 3 - 工作示例

当我从上面尝试解决方案时(在 Vue 3 中)我在控制台中得到了这个

[Vue Router warn]: <router-view> can no longer be used directly inside <transition> or <keep-alive>.
Use slot props instead:

<router-view v-slot=" Component ">
  <keep-alive>
    <component :is="Component" />
  </keep-alive>
</router-view>

所以我就这样把它复制到了App.vue中……

// App.vue
...
  <router-view v-slot=" Component ">
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
  </router-view>
...

它有效:)

【讨论】:

【参考方案3】:

我认为您无法使用keep-alive 缓存router-view。来自keep-alive的documentation:

keep-alive 不适用于功能组件,因为它们没有要缓存的实例。

router-view是一个功能组件,来自documentation:

该组件是一个功能组件,它为给定路径呈现匹配的组件。

要完成这项工作,您需要在 keep-alive 中添加动态组件,如下所示:

<keep-alive>
  <products ></products>
</keep-alive>

【讨论】:

您好,感谢您指出这一点!想到的第一个解决方案是删除&lt;router-view&gt; 并放回我的动态组件,例如:&lt;keep-alive&gt; &lt;component v-bind:is="$route.name"/&gt; &lt;/keep-alive&gt;其中路由的名称将是组件的名称。这在路由方面有效,但在两个版本之间单击时组件仍在重新安装:\ 似乎不再是真的了。引用router documentation:Since it's just a component, it works with &lt;transition&gt; and &lt;keep-alive&gt;. When using the both together, make sure to use &lt;keep-alive&gt; inside @oliverpool 您可以引用所有您想要的内容,但该文档示例不起作用。【参考方案4】:

看看我在这里为 vue 2+ 发布的内容:

vue.js keep-alive and router-view

如果您想根据路由 url 交换内容,您可以将子项添加到您的 routes.js 文件并以这种方式绑定参数。例如,如果您想让您的组件保持活动状态,但需要从部分路径更改数据,您可以执行以下操作:

 
  path: 'products', component: Products, ...,
  children: [
               path: 'Overview/:name', props: true, component: Overview ,
               path: 'Overview/:name/:id', props: true, component: Details 
            ]

您可以先路由到 /Products,然后说用户单击图像或您想要路由到 /Products/Overview/Memes 的任何列表,然后在用户单击可以路由到 /Products/Overview 的特定 meme 之后/Memes/MrPotatoHead 并让组件在 Mr Potato Head 或类似的东西上加载数据。

重要的是要注意 Products 组件将保持活动状态,但子组件不会。即使您将子组件模板包装在 keep-alive 中,它也会被销毁:

destroy nested keep-alive components

【讨论】:

【参考方案5】:

仅仅因为您的组件被重新安装并因此在 mounted 钩子上触发您的函数并不意味着它曾经被销毁。要测试它是否保持活动状态,请在 destroyed 钩子上记录一些内容,如果它没有触发控制台日志,则 keep-alive 正在工作。我已经运行了你的相同代码,它似乎至少在 Vue 2 中工作。

【讨论】:

以上是关于Vue 2 <keep-alive> 不能与 <router-view> 和密钥一起使用的主要内容,如果未能解决你的问题,请参考以下文章

vue keep-alive 使用思路

vue keep-alive 生命周期

vue keep-alive

vue中的keep-alive

Vue路由开启keep-alive缓存页面

前端框架vue中的keep-alive总结实践