Vuejs <keep-alive> 有什么意义?
What is the point of Vuejs <keep-alive>?
基本上,就是它所说的。 <keep-alive>
有什么意义?这听起来可能很愚蠢,但我认为目的是缓存与当前未在 DOM 中呈现的组件关联的数据。根据 this bug/issue,<keep-alive>
专门 设计用于在从页面中删除元素时删除它持有的缓存。那我错过了什么?
为什么我要将 <keep-alive>
与 v-show
一起使用? v-show
的重点不就是该元素仍然存在于页面上,只是将 CSS 设置为隐藏它吗?默认情况下,元素使用 v-show
隐藏时会丢失数据吗?
需要说明的是,下面的示例显然应该不起作用(根据我链接的已关闭 bug/issue):
<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>
在这种情况下会缓存与 <some-child-component>
关联的数据,一旦它被加载,并且如果用户点击显示(可能是很多数据出于性能原因,我不想在 DOM 中出现,除非用户专门单击以显示它,或其他)它会切换显示,但会保留搜索词或组件中发生的任何事情。
有没有一种方法可以重写它以符合 <keep-alive>
的预期功能?我是否必须绑定到 <component>
上的 is
,如果我现在不想让它呈现,就将其设置为空?是这样的吗?
<keep-alive>
<component :is="lazyLoaded && userClickedToShow ? 'SomeChildComponent' : ''" :prop="lazyLoaded && someLazyLoadedData"></component>
<keep-alive>
这似乎混淆了那里实际发生的事情,如果它真的有效的话。还假设 SomeChildComponent
的 prop 可以采用 false
,但它可能无法采用。我不喜欢那个选项。我想稍微好一点的是将整个东西包装在一个 if
块中,也许?
<div v-if="lazyLoaded">
<keep-alive>
<component :is="userClickedToShow ? : 'SomeChildComponent' : ''" :prop="someLazyLoadedData"></component>
<keep-alive>
</div>
当然,这假设 <keep-alive>
在 v-if
块中起作用,但它可能不会。此外,它仍然不如第一种方式(行不通)那么清晰。我不喜欢将 is
设置为 ''
除非那真的是唯一的方法。当然,这些选项都不允许条件控制更大的块,只有元素保持活动状态。
刚刚花了两天的大部分时间试图弄清楚为什么 <keep-alive>
无法让任何东西保持活力!希望有一些简单的东西我只是想念!
编辑:更新初始示例以更好地反映我的用例。
I thought the purpose was to cache data associated with an component not currently being rendered in the DOM
不,它不缓存组件的数据。它缓存整个组件实例(包括它的整个状态)。简单地说,它使组件实例存活而不是被销毁...
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?
从这个 "bug" 中得到的要点是 "whenever <keep-alive>
component is destroyed (because it is itself inside v-if
), it drops all cached components..."
Why would I want to use <keep-alive>
with 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
的要点,将它与 <keep-alive>
一起使用是没有意义的(因为 v-show
不会导致组件成为 destroyed/created )
By default, does an element lose data when it's hidden with v-show
?
不,被 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>
...是的,它不起作用,因为:
v-if === false
将销毁 <keep-alive>
组件(如果它之前被渲染过)(但这并不完全正确,因为 <keep-alive>
是 "render-less" 在某种意义上它只是提供功能和不向 DOM 呈现任何东西,除了它的子组件)。
- 并且
v-if === true
将创建 <keep-alive>
并呈现它的子组件
为了使其正常工作,您需要将 <keep-alive>
移到 v-if
之外:
<keep-alive>
<some-child-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
</keep-alive>
当 v-if
条件的结果为 true
时,上述代码应导致 some-child-component
被渲染(并同时放入 <keep-alive>
的缓存中) .当 v-if
切换到 false
时,组件的模板从 DOM 中删除,但组件保留在缓存中而不是被销毁。
在这种情况下,v-if
(连同 <keep-alive>
)和 v-show
之间的主要区别在于,对于 v-if
/keep-alive
组合,组件实例保存在内存中,但它的模板结果不是 DOM 的一部分,而对于 v-show
组件是活动的 和 相应的 HTML它呈现的是 DOM 的一部分(只是隐藏)
然后回答你的问题....<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>
由于与第一个示例相同的原因,此代码将无法按预期工作 - 如果 keep-alive
被破坏(由于 v-if
条件评估为 false
),它将删除所有缓存的组件。 keep-alive
只是本地缓存,只有当它本身是 "rendered".
时才会起作用
Is there a way to rewrite this that would fit with how is supposed to function?
你最好的选择就是将你想要的所有东西 "toggle" 包装到一个组件中,然后像这样使用该组件:
<keep-alive>
<my-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
</keep-alive>
...所有其他变体都会失败,您可以在 this demo
中尝试查看
Note, <keep-alive>
is designed for the case where it has one direct child component that is being toggled. When there are multiple conditional children, <keep-alive>
requires that only one child is rendered at a time.
- 如果它有多个 rendered child
,它将不起作用
- 如果子组件不是组件(例如
<div
),它将不起作用
基本上,就是它所说的。 <keep-alive>
有什么意义?这听起来可能很愚蠢,但我认为目的是缓存与当前未在 DOM 中呈现的组件关联的数据。根据 this bug/issue,<keep-alive>
专门 设计用于在从页面中删除元素时删除它持有的缓存。那我错过了什么?
为什么我要将 <keep-alive>
与 v-show
一起使用? v-show
的重点不就是该元素仍然存在于页面上,只是将 CSS 设置为隐藏它吗?默认情况下,元素使用 v-show
隐藏时会丢失数据吗?
需要说明的是,下面的示例显然应该不起作用(根据我链接的已关闭 bug/issue):
<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>
在这种情况下会缓存与 <some-child-component>
关联的数据,一旦它被加载,并且如果用户点击显示(可能是很多数据出于性能原因,我不想在 DOM 中出现,除非用户专门单击以显示它,或其他)它会切换显示,但会保留搜索词或组件中发生的任何事情。
有没有一种方法可以重写它以符合 <keep-alive>
的预期功能?我是否必须绑定到 <component>
上的 is
,如果我现在不想让它呈现,就将其设置为空?是这样的吗?
<keep-alive>
<component :is="lazyLoaded && userClickedToShow ? 'SomeChildComponent' : ''" :prop="lazyLoaded && someLazyLoadedData"></component>
<keep-alive>
这似乎混淆了那里实际发生的事情,如果它真的有效的话。还假设 SomeChildComponent
的 prop 可以采用 false
,但它可能无法采用。我不喜欢那个选项。我想稍微好一点的是将整个东西包装在一个 if
块中,也许?
<div v-if="lazyLoaded">
<keep-alive>
<component :is="userClickedToShow ? : 'SomeChildComponent' : ''" :prop="someLazyLoadedData"></component>
<keep-alive>
</div>
当然,这假设 <keep-alive>
在 v-if
块中起作用,但它可能不会。此外,它仍然不如第一种方式(行不通)那么清晰。我不喜欢将 is
设置为 ''
除非那真的是唯一的方法。当然,这些选项都不允许条件控制更大的块,只有元素保持活动状态。
刚刚花了两天的大部分时间试图弄清楚为什么 <keep-alive>
无法让任何东西保持活力!希望有一些简单的东西我只是想念!
编辑:更新初始示例以更好地反映我的用例。
I thought the purpose was to cache data associated with an component not currently being rendered in the DOM
不,它不缓存组件的数据。它缓存整个组件实例(包括它的整个状态)。简单地说,它使组件实例存活而不是被销毁...
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?
从这个 "bug" 中得到的要点是 "whenever <keep-alive>
component is destroyed (because it is itself inside v-if
), it drops all cached components..."
Why would I want to use
<keep-alive>
withv-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
的要点,将它与 <keep-alive>
一起使用是没有意义的(因为 v-show
不会导致组件成为 destroyed/created )
By default, does an element lose data when it's hidden with
v-show
?
不,被 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>
...是的,它不起作用,因为:
v-if === false
将销毁<keep-alive>
组件(如果它之前被渲染过)(但这并不完全正确,因为<keep-alive>
是 "render-less" 在某种意义上它只是提供功能和不向 DOM 呈现任何东西,除了它的子组件)。- 并且
v-if === true
将创建<keep-alive>
并呈现它的子组件
为了使其正常工作,您需要将 <keep-alive>
移到 v-if
之外:
<keep-alive>
<some-child-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
</keep-alive>
当 v-if
条件的结果为 true
时,上述代码应导致 some-child-component
被渲染(并同时放入 <keep-alive>
的缓存中) .当 v-if
切换到 false
时,组件的模板从 DOM 中删除,但组件保留在缓存中而不是被销毁。
在这种情况下,v-if
(连同 <keep-alive>
)和 v-show
之间的主要区别在于,对于 v-if
/keep-alive
组合,组件实例保存在内存中,但它的模板结果不是 DOM 的一部分,而对于 v-show
组件是活动的 和 相应的 HTML它呈现的是 DOM 的一部分(只是隐藏)
然后回答你的问题....<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>
由于与第一个示例相同的原因,此代码将无法按预期工作 - 如果 keep-alive
被破坏(由于 v-if
条件评估为 false
),它将删除所有缓存的组件。 keep-alive
只是本地缓存,只有当它本身是 "rendered".
Is there a way to rewrite this that would fit with how is supposed to function?
你最好的选择就是将你想要的所有东西 "toggle" 包装到一个组件中,然后像这样使用该组件:
<keep-alive>
<my-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
</keep-alive>
...所有其他变体都会失败,您可以在 this demo
中尝试查看Note,
<keep-alive>
is designed for the case where it has one direct child component that is being toggled. When there are multiple conditional children,<keep-alive>
requires that only one child is rendered at a time.
- 如果它有多个 rendered child ,它将不起作用
- 如果子组件不是组件(例如
<div
),它将不起作用