[英]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>
withv-show
?为什么我要使用
<keep-alive>
和v-show
? Isn't the whole point ofv-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 : ...是的,它不起作用,因为:
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 渲染任何东西,除了它的子组件)。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 设计的...
<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 ...所有其他变体都将失败,您可以尝试在此演示中查看
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>
要求一次只渲染一个子节点。
<div
)<div
),它将不起作用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.