keep-alive是vue内置的组件,是用来缓存切换时不想被销毁的组件。一般情况下我们组件切换时时销毁组件的,切换回来时又重新加载,这种情况有时会浪费性能,而且不利于用户体验。
尝试一下
注意。这里使用v3,展示,我的vue-router版本是4.0+ 不能使用keep-alive包括router-link。v2可以直接写 app.vue
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>
a.vue
<template>
这是a组件:<router-link to="/b">去b组件</router-link>
<br />
count:{{ count }} ---<button @click="count += 1">count+1</button>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(1);
</script>
b.vue 相同代码 不过a换成b 下面结果ab切换不会变化
include,exclude
匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值) 。匿名组件不能被匹配。include和exclude里面可以写字符串,正则,数组 app.vue include是能缓存的对象 exclude是不能缓存的 下面的include的 exclude同理
<template>
<router-view v-slot="{ Component }">
<keep-alive include="a"><!-- 字符串 -->
<!-- <keep-alive :include="/a/"> 正则-->
<!-- <keep-alive :include="["a"]"> 数组 -->
<component :is="Component" />
</keep-alive>
</router-view>
</template>
activated,deactivated
组件被缓存的时候没有被销毁掉,所以下次进入的时候不会被重新创建。所以官方提供了activated,deactivated2个生命周期的钩子。一个是进入缓存时 一个是离开缓存时。我们就可以在这2个钩子里面执行我们自己的操作 a.vue
<template>
这是a组件:<router-link to="/b">去b组件</router-link>
<br />
count:{{ count }} ---<button @click="count += 1">count+1</button>
</template>
<script setup>
import { ref, onActivated, onDeactivated } from 'vue';
const count = ref(1);
onActivated(() => {
console.log('缓存开始了');
});
onDeactivated(() => {
console.log('缓存结束了');
});
</script>
遇到的问题
你在组件初始化的时候去拿路由信息,或者其他信息去加载页面,但是缓存页面没有初始化这个阶段,你就不能执行这个操作,所以当你重新进入缓存页面的时候就不会加载信息。比如现在a组件里面由一个tabs,下面是2个组件,分别是新闻和运动,对应路由query参数type==news or sport。setup拿到type 然后对应加载。现在需求是缓存a组件,比如我在游览体育新闻,我在b组件跳回a组件的时候,需要展示体育新闻
<template>
<router-view v-slot="{ Component }">
<keep-alive include="a">
<component :is="Component" />
</keep-alive>
</router-view>
</template>
<template>
这是a组件:<router-link to="/b">去b组件</router-link>
<br />
<div
class="tabs"
@click="
router.push({
path: '/a',
query: {
type: 'news'
}
})
"
:class="router.currentRoute.value.query.type == 'news' ? 'active' : ''"
>
新闻
</div>
<div
class="tabs"
@click="
router.push({
path: '/a',
query: {
type: 'sport'
}
})
"
:class="router.currentRoute.value.query.type == 'sport' ? 'active' : ''"
>
体育
</div>
<div class="content" v-if="router.currentRoute.value.query.type == 'news'">
新闻内容
</div>
<div class="content" v-if="router.currentRoute.value.query.type == 'sport'">
体育内容
</div>
</template>
<script setup>
import { ref, onActivated, onDeactivated } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const type = ref(router.currentRoute.value.query.type || 'news');
</script>
这时候你从b组件跳回a的时候,就没有信息展示
解决办法
记录页面选中参数,进入缓存时读取参数
<template>
这是a组件:<router-link to="/b">去b组件</router-link>
<br />
<div
class="tabs"
@click="tabsClick('news')"
:class="type == 'news' ? 'active' : ''"
>
新闻
</div>
<div
class="tabs"
@click="tabsClick('sport')"
:class="type == 'sport' ? 'active' : ''"
>
体育
</div>
<div class="content" v-if="type == 'news'">新闻内容</div>
<div class="content" v-if="type == 'sport'">体育内容</div>
</template>
<script setup>
import { ref, onActivated } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const type = ref(router.currentRoute.value.query.type || 'news');
const tabsClick = (checked) => {
type.value = checked;
router.push({ path: '/a', query: { type: checked } });
};
onActivated(() => {
router.push({ path: '/a', query: { type: type.value } });
});
</script>
同理 还有屏幕滚动高度这些也是一样的,在进入缓存时读取,优化用户体验