方案 1:正确配置 keep-alive
keep-alive
是一个内置组件,它能对组件实例进行缓存,避免重复创建和销毁组件,进而提升应用性能
使用场景
- 频繁切换的组件:当在多个组件间频繁切换时,若不使用
keep-alive
,每次切换都会重新创建组件实例,会消耗较多性能。使用keep-alive
后,组件实例会被缓存,再次切换时直接从缓存中获取,无需重新创建。 - 需要保留状态的组件:有些组件在切换出去后,需要保留之前的状态,比如滚动位置、输入框内容等。使用
keep-alive
可以让组件状态得以保留。
使用方法
1. 包裹路由组件(缓存路由组件)
若要对路由组件进行缓存,可在 App.vue
里用 keep-alive
包裹 router-view
组件。
app.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
</script>
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>
<style scoped>
</style>
2. 包裹普通组件(缓存动态组件)
若要对普通组件进行缓存,可直接用 keep-alive
包裹该组件。
代码:
keepalive/index.vue
<template>
<el-button @click="()=>this.iscomponent='A'">切换A</el-button>
<el-button @click="()=>this.iscomponent='B'">切换B</el-button>
<keep-alive>
<component :is="iscomponent"></component>
</keep-alive>
</template>
<script>
import A from "./components/A.vue"
import B from "./components/B.vue"
export default {
components: {
A,
B
},
data(){
return {
iscomponent:'A'
}
}
}
</script>
keepalive/components/A.vue
<template>
姓名:
<input/>
</template>
keepalive/components/B.vue
<template>
年龄:
<input/>
</template>
效果:
3. 结合 include
和 exclude
属性
include
和 exclude
属性可用于指定哪些组件需要被缓存或者哪些组件不需要被缓存。这两个属性的值可以是字符串、正则表达式或者数组。
app.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
</script>
<template>
<router-view v-slot="{ Component }">
<keep-alive include="KeepAliveRouter">
<component :is="Component" />
</keep-alive>
</router-view>
</template>
<style scoped>
</style>
router.js
{
path: '/keepaliverouter',
name: 'KeepAliveRouter',
component: ()=>import('@/views/keepaliverouter/index.vue'),
},
相关生命周期钩子
当组件被 keep-alive
缓存时,其 created
、mounted
等生命周期钩子只会在第一次创建时执行,之后从缓存中获取组件实例时不会再次执行。不过,会新增 activated
和 deactivated
两个生命周期钩子。
activated
:组件被激活时调用,也就是从缓存中取出组件并显示时调用。deactivated
:组件被停用(放入缓存)时调用。
<template>
<div>
这是一个被缓存的组件
</div>
</template>
<script>
export default {
name: 'CachedComponent',
activated() {
console.log('组件被激活');
},
deactivated() {
console.log('组件被停用');
}
};
</script>
注意事项
- 组件
name
属性:使用include
和exclude
属性时,要确保组件的name
属性已正确设置,因为这两个属性是依据组件的name
来进行匹配的。 - 内存占用:尽管
keep-alive
能提升性能,但过多使用可能会增加内存占用,所以要合理使用。
方案 2:结合 Vuex 状态管理
定义 Store:
// store/form.js
export default {
state: {
formData: {}
},
mutations: {
SAVE_FORM_DATA(state, data) {
state.formData = data;
}
}
};
在组件中使用
<script>
export default {
computed: {
...mapState(['formData'])
},
methods: {
...mapMutations(['SAVE_FORM_DATA'])
}
}
</script>
方案 3:本地存储备份
// 保存数据到 localStorage
localStorage.setItem('formData', JSON.stringify(this.formData));
// 从 localStorage 恢复数据
const savedData = localStorage.getItem('formData');
if (savedData) {
this.formData = JSON.parse(savedData);
}
完整代码示例
vue
<!-- FormPage.vue -->
<template>
<form>
<input v-model="formData.name" placeholder="姓名">
<input v-model="formData.email" placeholder="邮箱">
<button @click="submit">提交</button>
</form>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
export default {
name: 'FormPage',
data() {
return {
formData: {}
};
},
activated() {
// 优先从 Vuex 恢复数据
if (this.formData) return;
// 从 localStorage 备份恢复
const savedData = localStorage.getItem('formData');
if (savedData) {
this.formData = JSON.parse(savedData);
}
},
deactivated() {
this.SAVE_FORM_DATA(this.formData);
localStorage.setItem('formData', JSON.stringify(this.formData));
},
computed: {
...mapState(['formData'])
},
methods: {
...mapMutations(['SAVE_FORM_DATA']),
submit() {
// 提交逻辑
console.log('提交数据:', this.formData);
// 提交后清空缓存(可选)
this.SAVE_FORM_DATA({});
localStorage.removeItem('formData');
}
}
};
</script>
提交表单后,通过 localStorage.removeItem
或 Vuex 清空数据,避免下次进入页面时显示旧数据。
方案对比
方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
keep-alive |
简单易用,自动缓存 | 依赖组件 name ,无法持久化 |
短期缓存(不关闭页面) |
Vuex + keep-alive |
数据全局共享,支持持久化 | 需额外配置 Vuex | 复杂状态管理 |
本地存储 | 数据持久化,支持跨页面 / 重启 | 数据可能过时,需手动清理 | 需要长期保存数据 |