【问题标题】:What is the point of Vuejs <keep-alive>?Vuejs <keep-alive> 的意义何在?
【发布时间】:2020-01-20 22:21:38
【问题描述】:

基本上,它说的是什么。 &lt;keep-alive&gt; 有什么意义?这可能听起来很傻,但我认为其目的是缓存与当前未在 DOM 中呈现的组件关联的数据。根据this bug/issue 的说法,&lt;keep-alive&gt; 专门被设计为在从页面中删除元素时删除它所持有的缓存。那我错过了什么?

我为什么要将&lt;keep-alive&gt;v-show 一起使用? v-show 的重点不是该元素仍然存在于页面上,只是将 CSS 设置为隐藏它?默认情况下,使用v-show 隐藏元素时会丢失数据吗?

需要明确的是,以下示例显然应该不起作用(根据我链接的已关闭错误/问题):

<div v-if="lazyLoaded && userClickedToShow">
    <h2>{{someLazyLoadedData.title}}</h2>
    <div id="otherStuff">
        ...
    </div>
    <keep-alive>
        <some-child-component :prop="someLazyLoadedData"></some-child-component>
    </keep-alive>
</div>

所以我本来希望&lt;keep-alive&gt; 在这种情况下会在加载后缓存与&lt;some-child-component&gt; 关联的数据,如果用户点击显示(也许这是我不想要的很多数据出于性能原因在 DOM 中,除非用户专门单击以显示它,或者其他什么)它会切换显示,但保留搜索词或组件中发生的任何事情。

有没有办法重写它以适应&lt;keep-alive&gt; 的功能?我是否必须在&lt;component&gt; 上绑定到is,如果我现在不希望它渲染,只需将其设置为空?像这样?

<keep-alive>
    <component :is="lazyLoaded && userClickedToShow ? 'SomeChildComponent' : ''" :prop="lazyLoaded && someLazyLoadedData"></component>
<keep-alive>

这似乎混淆了那里实际发生的事情,如果它甚至有效的话。还假设SomeChildComponent 的道具可以采用false,它可能无法做到。我不喜欢那个选项。我想稍微好一点的方法是将整个东西包装在一个 if 块中,也许?

<div v-if="lazyLoaded">
    <keep-alive>
        <component :is="userClickedToShow ? : 'SomeChildComponent' : ''" :prop="someLazyLoadedData"></component>
    <keep-alive>
</div>

当然,这假定&lt;keep-alive&gt;v-if 块中起作用,但它可能不会。此外,它仍然不如第一种方式清晰(这不起作用)。我不喜欢将is 设置为'',除非那真的是唯一的方法。当然,这些选项都不允许条件控制更大的块,只有元素保持活动状态。

刚刚花了两天的大部分时间试图弄清楚为什么&lt;keep-alive&gt; 无法让任何东西保持活力!希望我只是缺少一些简单的东西!

编辑:更新初始示例以更好地反映我的用例。

【问题讨论】:

    标签: javascript vue.js vuejs2 preprocessor-directive


    【解决方案1】:

    我认为目的是缓存与当前未在 DOM 中呈现的组件关联的数据

    不,它不会缓存组件的数据。它缓存整个组件实例(包括它的整个状态)。简单地说就是让组件实例存活而不是被销毁......

    根据this bug,专门设计用于在从页面中删除元素时删除它所持有的缓存。那我错过了什么?

    从这个“错误”中得到的要点是“每当 &lt;keep-alive&gt; 组件被销毁时(因为它本身在 v-if 中),它会删除所有缓存的组件......”

    我为什么要将&lt;keep-alive&gt;v-show 一起使用? v-show 的重点不是该元素仍然存在于页面上,只是将 CSS 设置为隐藏它?

    是的,这正是v-show 的意义所在,将它与&lt;keep-alive&gt; 一起使用是没有意义的(因为v-show 不会导致组件被销毁/创建)

    默认情况下,使用v-show 隐藏元素时会丢失数据吗?

    不,v-show 隐藏的组件仍然存在于内存、组件树和 DOM 中并保持其状态......

    需要明确的是,以下示例显然应该不起作用(根据我仍然链接的已关闭错误)

    <div v-if="lazyLoaded && userClickedToShow">
        <keep-alive>
             <some-child-component :prop="someLazyLoadedData"></some-child-component>
        </keep-alive>
    </div>
    

    ...是的,它不起作用,因为:

    1. v-if === false 将销毁 &lt;keep-alive&gt; 组件,如果它以前被渲染过(但这并不完全正确,因为 &lt;keep-alive&gt; 在某种意义上是“无渲染”的,它只是提供功能并且不会向 DOM 渲染任何东西,除了它的孩子零件) 。
    2. v-if === true 将创建 &lt;keep-alive&gt; 并渲染它的子组件

    为了让它工作,你需要将&lt;keep-alive&gt;移到v-if之外:

    <keep-alive>
        <some-child-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
    </keep-alive>
    

    v-if 条件的结果为true 时,上面的代码应该导致some-child-component 被渲染(并同时放入&lt;keep-alive&gt; 的缓存中)。当v-if 切换到false 时,组件的模板会从 DOM 中移除,但组件会保留在缓存中而不是被销毁。

    v-if(连同&lt;keep-alive&gt;)和v-show在这种情况下的主要区别在于v-if/keep-alive组合,组件实例保存在内存中,但它的模板的结果不是DOM 的一部分,而对于v-show,组件是活动的并且它呈现的相应 HTML 是 DOM 的一部分(只是隐藏)

    回答你的问题....&lt;keep-alive&gt; 主要是为动态组件 (&lt;component :is="" &gt;) 和 Vue-router 设计的...

    更新(...因为有问题的更新代码)

    <div v-if="lazyLoaded && userClickedToShow">
        <h2>{{someLazyLoadedData.title}}</h2>
        <div id="otherStuff">
            ...
        </div>
        <keep-alive>
            <some-child-component :prop="someLazyLoadedData"></some-child-component>
        </keep-alive>
    </div>
    

    由于与第一个示例相同的原因,此代码不会按预期工作 - 如果 keep-alive 被破坏(由于 v-if 条件评估为 false),它将删除所有缓存的组件。 keep-alive 只是本地缓存,只有当它本身被“渲染”时才会起作用。

    有没有办法重写它以符合应该如何运作?

    您最好的选择是将您想要“切换”的所有内容包装到单个组件中并像这样使用该组件:

    <keep-alive>
      <my-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
    </keep-alive>
    

    ...所有其他变体都将失败,您可以在 this demo 中尝试查看

    Docs

    请注意,&lt;keep-alive&gt; 专为具有一个正在切换的直接子组件 的情况而设计。当有多个条件子级时,&lt;keep-alive&gt; 要求一次只渲染一个子级。

    • 如果它有多个渲染子节点,它将不起作用
    • 如果子元素不是组件(例如&lt;div),它将不起作用

    【讨论】:

    • 我想我最初的例子还不够完整。问题是我想要有条件地渲染整个部分,而不仅仅是单个子组件。 &lt;keep-alive&gt; 在 DOM 中时缓存,所以如果我只是在初始延迟加载检查中包装块,之后它会保持缓存,对吗?
    • 缓存的组件实例还没有运行,是吗?
    猜你喜欢
    • 2018-07-08
    • 2016-09-07
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2023-03-07
    • 2021-07-20
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多