缓存组件

<KeepAlive>
Introduction
. 现实:多个组件间动态切换时,默认情况下,组件被替换掉 | unmount,再次回来时,状态被挂载 | onmount,并重新初始化,类似于 v-if 的执行
. 需求:特定情况下,当组件恢复时,为了继续使用其状态 | 恢复现场,需要缓存 | 保留被移除的组件实例;同:函数的执行、调试断点
. 方案:使用内置组件 <KeepAlive> 缓存组件实例
<KeepAlive>
  <component :is="tabs[currentTab]"></component>
</KeepAlive>
Feature
. 默认会缓存内部的所有组件实例 - 主要面向 动态组件
. 路由视图 <RouerView> 也是一个动态组件;但是需要特别处理;见后续案例
. 可以使用属性 include 和 exclude 属性定制缓存行为
. 还可以使用属性 max 指定最大缓存组件数
Application
. 各管理平台的标签页应用
<KeepAlive>属性
属性 说明
include 需要缓存的组件
exclude 不需要缓存的组件
max 最大缓存组件数
lifecycle
. 缓存实例的 生命周期函数
. 组件缓存后而仍作为组件树的一部分时,它将变为不活跃状态而不是被卸载
1. onActivated()
. 注册一个回调函数,若组件实例是 <KeepAlive> 缓存树的一部分,当组件被插入到 DOM 中时调用
2. onDeactivated()
. 注册一个回调函数,若组件实例是 <KeepAlive> 缓存树的一部分,当组件从 DOM 中被移除时调用
Drill
[] 标签页组件 - 动态组件缓存版
为每个组件增加 2 个 生命周期函数/钩子,当标签页切换时,查看组件的加载和激活状态;如
onActivated(() => {
  console.log('TabGoods onActivated');
})
onDeactivated(() => {
  console.log('TabGoods onDeactivated');
})
使用缓存组件包裹动态组件,修改结构如下
<span v-for="(item, ind) in com" @click="index = ind">{{ item.tag }}</span>
<KeepAlive>
  <component :is="com[index].component"></component>
</KeepAlive>
查看组件切换时,控制台的输出
Summary
<KeepAlive>的属性
<KeepAlive>的生命周期
<KeepAlive>的事件
<KeepAlive>的应用
Homework
[] 路由视图缓存
. 避免初始化逻辑重复执行,如数据加载
. 不是简单的使用缓存组件包裹,而应该使用动态组件实现;注意查看浏览器的提示信息
. v-slot="{ Component }" 是 Vue 3 中用于接收 作用域插槽 scoped slot 传递数据的语法:从 <RouterView> 接收当前激活的路由组件
<RouterView v-slot="{ Component }">
  <KeepAlive>
    <component :is="Component" />
  </KeepAlive>
</RouterView>
其它方案:使用前先判断
父组件
<div class="father">
  <MallPinia></MallPinia>
</div>
import MallPinia from '@/components/MallPinia.vue';
子组件
onMounted(async () => {
  if (!goodsStore.goods.length) {
    console.log('first');
    goods.value = await goodsStore.getAll();
  } else {
    goods.value = goodsStore.goods;
  }
})
如何缓存特定路由?
[] 缓存项目中其它业务部分