背景:在vue3 h5开发中,在列表的详情页里有一个tabs组件,点击某一个tab下面的内容进入子页面,从子页面返回详情页的时候由于页面重新进行了初始化,没有保留之前选中的tab,产品提出优化需求。于是想起了keep-alive这个内置组件。
App.vue
用store把include
的内容做成动态的,包含某个页面的时候会把该页面加入缓存,移除某个页面的时候会把该页面移出缓存。
<router-view v-slot="{ Component }">
<keep-alive :include="orderStore.keepAlivePages">
<component :is="Component" />
</keep-alive>
</router-view>
import { useOrderStore } from "@/store"
const orderStore = useOrderStore();
store/order.ts
store里面有setKeepAlivePages(添加缓存页面),和removeKeepAlivePage(移除缓存页面)的方法。
state: () => ({
keepAlivePages: []
}),
actions: {
// 添加需要keep-alive的页面
setKeepAlivePages(data: string) {
if (this.keepAlivePages.includes(data)) return;
this.keepAlivePages.push(data);
},
// 移除需要去除keep-alive的页面
removeKeepAlivePage(data: string) {
if (!this.keepAlivePages.includes(data)) return;
const index = this.keepAlivePages.indexOf(data);
this.keepAlivePages.splice(index, 1);
}
}
acceptanceDetail.vue——详情页
进入详情页的时候把页面加入缓存。
它会根据组件的
name
选项进行匹配,所以组件如果想要条件性地被KeepAlive
缓存,就必须显式声明一个name
选项。
import { useOrderStore } from "@/store"
const orderStore = useOrderStore();
// composition api可以通过defineOptions来设置name选项
defineOptions({
name: "AcceptanceDetail"
});
// 刚进入页面的时候会执行onMounted
onMounted(() => {
orderStore.setKeepAlivePages("AcceptanceDetail");
initData();
});
// 页面被添加到keep-alive里面之后会执行onActivated
// 在这里写组件被激活后的操作
onActivated(() => {
initData();
});
acceptanceList.vue——列表页
回到列表页的时候清除缓存。做这一步是因为发现在详情页里面虽然可以通过onActivated生命周期钩子重新请求数据,但是tabs组件还是缓存了,即使重新初始化也不行。导致从列表页点击一个新的订单进来详情页,新订单的详情页的tab选中的还是上一个订单的。所以想到清除缓存。
import { useOrderStore } from "@/store"
const orderStore = useOrderStore();
onMounted(() => {
orderStore.removeKeepAlivePage("AcceptanceDetail");
});