【问题标题】:Vue 2 <keep-alive> not working with <router-view> and keyVue 2 <keep-alive> 不能与 <router-view> 和密钥一起使用
【发布时间】: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 视图变成一个单独的组件?

【问题讨论】:

标签: javascript vue-component vue-router vue.js


【解决方案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-alivedocumentation

    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 documentationSince 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 中工作。

      【讨论】:

        猜你喜欢
        • 2018-09-06
        • 2012-05-09
        • 2017-01-25
        • 2018-03-31
        • 1970-01-01
        • 2011-01-13
        • 2016-09-07
        • 1970-01-01
        • 2020-08-25
        相关资源
        最近更新 更多