<keepAlive>
包裹动态组件时,可以将组件缓存起来。例如我们要浏览商品,可能点击详情后返回仍然在当前位置,不进行更新,这时候就要用到他。
我们首先想到的肯定是可以用他将需要缓存的子组件包裹起来就行了,但是这样在只有几个小页面中的项目可行,项目大了就复杂且难以维护。
我们可以通过路由中配置一个自定义meta属性来决定是否缓存。
- 我们可以在根组件中使用v-if的方式来进行判断组件是否缓存。
1.1
js
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
1.2
js
<router-view v-slot="{ Component, route }"> // 这里解构出路由对象和组件对象,不是插槽,是新用法
<keep-alive>
<component :is="Component" v-if="route.meta.keepAlive"/>
</keep-alive>
<component :is="Component" v-if="!route.meta.keepAlive"/>
</router-view>
- 通过 keepAlive自带的属性进行绑定。 他有三个属性可以进行设置
我们通过include属性来进行一个动态绑定。当我们是从进入详情页面返回的时候,我们不进行缓存,当我们从最初页面平级跳转,我们清除缓存。
我们现在组件使用给keepAlive包裹一下:
js
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="cachedComponents">
<component :is="Component" />
</keep-alive>
</router-view>
</template>
<script setup>
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
const cachedComponents = ref([])
const route = useRoute()
watch(route, (newVal,old) => {
if (newVal.meta.keepAlive && !cachedComponents.value.includes(newVal.name)) {
if(newVal.meta.deep > )
cachedComponents.value.push(newVal.name)
}
})
</script>
我们先来设置一下路由:
js
// router/index.ts
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [
{
path: '/list',
name: 'List',
component: () => import('@/views/List.vue'),
meta: {
depth: 1 // 添加层级标记
}
},
{
path: '/detail/:id',
name: 'Detail',
component: () => import('@/views/Detail.vue'),
meta: {
depth: 2
}
},
{
path: '/settings',
name: 'Settings',
component: () => import('@/views/Settings.vue'),
meta: {
depth: 1
}
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
// 缓存管理逻辑
const cachePages = ref<string[]>([])
router.beforeEach((to, from) => {
// 判断是否是前进更深层级
const isEnteringDeeper = (to.meta.depth as number) > (from.meta.depth as number)
// 判断是否是返回操作
const isGoingBack = (to.meta.depth as number) < (from.meta.depth as number)
if (isEnteringDeeper) {
// 进入更深层级时缓存前一个页面
if (!cachePages.value.includes(from.name as string)) {
cachePages.value.push(from.name as string)
}
} else if (!isGoingBack) {
// 平级切换时移除前一个页面的缓存
const index = cachePages.value.indexOf(from.name as string)
if (index > -1) {
cachePages.value.splice(index, 1)
}
}
})
keepAlive有两个生命周期钩子,onactived 和 onDeactived。 当我们的被缓存的页面显示时,会触发onactived钩子,隐藏时会触发 onDeactived钩子,触发顺序为 onCreated onMounted on Deactived。
路由守卫会在onDeactived之前执行。确保一些逻辑的完成。
我们可以利用onactived钩子来进行一些数据的更新。