简体   繁体   English

Vuejs 的意义何在<keep-alive> ?

[英]What is the point of Vuejs <keep-alive>?

Basically, what it says.基本上,它所说的。 What is the point of <keep-alive> ? <keep-alive>的意义何在? This might sound silly, but I thought the purpose was to cache data associated with an component not currently being rendered in the DOM.这听起来可能很傻,但我认为其目的是缓存与当前未在 DOM 中呈现的组件关联的数据。 According to this bug/issue , <keep-alive> is specifically designed to drop the cache it was holding when an element was removed from the page.根据这个错误/问题<keep-alive>专门设计用于在从页面中删除元素时删除它所持有的缓存。 So what am I missing?那么我错过了什么?

Why would I want to use <keep-alive> with v-show ?为什么我要使用<keep-alive>v-show Isn't the whole point of v-show that the element still exists on the page, just has CSS set to hide it? v-show的全部意义不在于该元素仍然存在于页面上,只是将 CSS 设置为隐藏它? By default, does an element lose data when it's hidden with v-show ?默认情况下,使用v-show隐藏元素时会丢失数据吗?

To be clear, the follow example is apparently supposed to not work (according to the closed bug/issue I linked anyway):需要明确的是,以下示例显然应该不起作用(根据我链接的已关闭错误/问题):

<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>

So I would have expected that <keep-alive> in this scenario would have cached data associated with the <some-child-component> once it was loaded, and if the user clicks to show (maybe it's a lot of data that I don't want in the DOM for performance reasons unless the user specifically clicks to show it, or whatever) it toggles the display, but keeps the search terms or whatever happened in the component.所以我希望<keep-alive>在这种情况下会在加载后缓存与<some-child-component>关联的数据,并且如果用户单击以显示(也许这是我没有的很多数据'出于性能原因不希望在 DOM 中,除非用户专门单击以显示它,或其他)它切换显示,但保留搜索词或组件中发生的任何事情。

Is there a way to rewrite this that would fit with how <keep-alive> is supposed to function?有没有办法重写这个适合<keep-alive>应该如何运作? Do I have to bind to is on a <component> and just set it to nothing if I don't want it to render at the moment?我是否必须绑定到<component>上的is并且如果我现在不希望它呈现,只需将其设置为空? Something like this?像这样的东西?

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

That seems to obfuscate what is actually happening there, if it even works.这似乎混淆了那里实际发生的事情,如果它甚至有效的话。 Also assuming that SomeChildComponent 's prop can take false , which it might not be able to.还假设SomeChildComponent的道具可以采用false ,它可能无法做到。 I'm not a fan of that option.我不喜欢那个选项。 Slightly better I guess would be to wrap the whole thing in an if block, maybe?我想稍微好一点的方法是将整个东西包装在一个if块中,也许?

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

Of course, this assumes that <keep-alive> functions within a v-if block, which it might not.当然,这假设<keep-alive>v-if块中起作用,它可能不会。 Also, it's still less clear than the first way (that doesn't work).此外,它仍然不如第一种方式清晰(这不起作用)。 I'm not a fan of setting is to '' unless that's really the only way.我不喜欢设置is '' ,除非那真的是唯一的方法。 And of course, neither of these options allow for larger blocks to be controlled by the conditional, only the element being kept alive.当然,这些选项都不允许条件控制更大的块,只有元素保持活动状态。

Just spent the better part of a two days trying to figure out why <keep-alive> was failing to keep anything alive!刚刚花了两天的大部分时间试图弄清楚为什么<keep-alive>无法让任何东西保持活力! Hopefully there's something simple I'm just missing!希望有一些简单的东西我只是想念!

Edit: updated initial example to better reflect my use-case.编辑:更新初始示例以更好地反映我的用例。

I thought the purpose was to cache data associated with an component not currently being rendered in the DOM我认为目的是缓存与当前未在 DOM 中呈现的组件相关联的数据

No, it doesn't cache component's data.不,它不会缓存组件的数据。 It caches whole component instance (including it's whole state).它缓存整个组件实例(包括它的整个状态)。 Simply it makes the component instance to live instead of being destroyed...简单地说,它使组件实例存活而不是被破坏......

According to this bug , is specifically designed to drop the cache it was holding when an element was removed from the page.根据这个错误,专门设计用于从页面中删除元素时删除它所持有的缓存。 So what am I missing?那么我错过了什么?

Point to take from this "bug" is "whenever <keep-alive> component is destroyed (because it is itself inside v-if ), it drops all cached components..."从这个“错误”中得到的一点是“每当<keep-alive>组件被销毁时(因为它本身在v-if内),它会删除所有缓存的组件......”

Why would I want to use <keep-alive> with v-show ?为什么我要使用<keep-alive>v-show Isn't the whole point of v-show that the element still exists on the page, just has CSS set to hide it? v-show的全部意义不在于该元素仍然存在于页面上,只是将 CSS 设置为隐藏它?

Yes, it is exactly the point of v-show and it makes no sense to use it with <keep-alive> (because v-show does not result in component being destroyed/created)是的,这正是v-show的重点,将它与<keep-alive>一起使用是没有意义的(因为v-show不会导致组件被销毁/创建)

By default, does an element lose data when it's hidden with v-show ?默认情况下,使用v-show隐藏元素时会丢失数据吗?

No, the component hidden by v-show still exists in memory, in component tree and the DOM and keeps it's state....不,被v-show隐藏的组件仍然存在于内存、组件树和 DOM中并保持它的状态....

To be clear, the follow example is apparently supposed to not work (according to the closed bug I linked anyway)需要明确的是,以下示例显然应该不起作用(根据我链接的已关闭错误)

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

...yes its doesn't work because : ...是的,它不起作用,因为:

  1. v-if === false will destroy the <keep-alive> component if it was previously rendered (but it's not entirely correct because <keep-alive> is "render-less" in the sense it just provide functionality and doesn't render anything to the DOM except it's child component) . v-if === false将破坏<keep-alive>组件,如果它以前被渲染(但这并不完全正确,因为<keep-alive>在某种意义上是“无渲染”的,它只是提供功能而不是向 DOM 渲染任何东西,除了它的子组件)。
  2. And v-if === true will create the <keep-alive> and render it's child components v-if === true将创建<keep-alive>并渲染它的子组件

In order to make it work, you need to move <keep-alive> outside of v-if :为了使其工作,您需要将<keep-alive>移到v-if之外:

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

Above code should result in some-child-component to be rendered (and put inside <keep-alive> 's cache at the same time) when result of v-if condition is true .v-if条件的结果为true时,上面的代码应该导致some-child-component被渲染(并同时放入<keep-alive>的缓存中)。 When v-if is switched to false , component's template is removed from DOM but component remains in the cache instead of being destroyed.v-if切换为false时,组件的模板会从 DOM 中移除,但组件仍保留在缓存中而不是被销毁。

Main difference between v-if (together with <keep-alive> ) and v-show in this case is that with v-if / keep-alive combo, the component instance is kept in the memory but result of it's template is not part of the DOM, whereas for v-show the component is alive and the corresponding HTML it renders is part of the DOM (just hidden)在这种情况下, v-if (与<keep-alive>一起)和v-show之间的主要区别在于,使用v-if / keep-alive组合,组件实例保留在内存中,但它的模板的结果不是一部分DOM 的一部分,而对于v-show组件是活动的,并且它呈现的相应 HTML 是 DOM 的一部分(只是隐藏)

And to answer your question.... <keep-alive> is primarily designed for dynamic component's ( <component :is="" > ) and Vue-router in particular...并回答您的问题.... <keep-alive>主要是为动态组件( <component :is="" > )和 Vue-router 设计的...

UPDATE (...because of updated code in question)更新(...因为有问题的更新代码)

<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>

This code won't work as expected for the same reason as 1st example - if keep-alive is destroyed (as a result of v-if condition evaluated to false ), it will drop all cached components.由于与第一个示例相同的原因,此代码不会按预期工作 - 如果keep-alive被破坏(由于v-if条件评估为false ),它将删除所有缓存的组件。 keep-alive is simply local cache which will work only if it is itself "rendered". keep-alive只是本地缓存,仅当它本身“渲染”时才会起作用。

Is there a way to rewrite this that would fit with how is supposed to function?有没有办法重写它以适应应该如何运作?

Your best option is just to wrap everything you want "toggle" into single component and use that component like this:您最好的选择是将您想要“切换”的所有内容包装到单个组件中并像这样使用该组件:

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

...all other variants will fail as you can try and see in this demo ...所有其他变体都将失败,您可以尝试在此演示中查看

Docs文档

Note, <keep-alive> is designed for the case where it has one direct child component that is being toggled.请注意, <keep-alive>是为它有一个正在切换的直接子组件的情况而设计的。 When there are multiple conditional children, <keep-alive> requires that only one child is rendered at a time.当有多个条件子节点时, <keep-alive>要求一次只渲染一个子节点。

  • it won't work if it has more than one rendered child如果它有多个渲染的孩子,它将不起作用
  • it won't work if the child is not a component (for example <div )如果孩子不是组件(例如<div ),它将不起作用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM