在Vue中,<keep-alive>
的include
属性用于指定需要缓存的组件,其实现方式如下:
1. 基本用法
• 字符串形式:通过逗号分隔组件名称,匹配到的组件会被缓存。
<keep-alive include="ComponentA,ComponentB">
<component :is="currentComponent"></component>
</keep-alive>
此时仅缓存名称为ComponentA
和ComponentB
的组件。
• 正则表达式:使用v-bind
动态绑定正则表达式,匹配组件名称。
<keep-alive :include="/Component[A-Z]/">
<component :is="currentComponent"></component>
</keep-alive>
此时匹配名称以Component
开头且后续为大写字母的组件。
• 数组形式:通过数组动态指定缓存组件。
<keep-alive :include="['ComponentA', 'ComponentB']">
<component :is="currentComponent"></component>
</keep-alive>
支持动态计算属性返回数组,例如结合路由元信息。
2. 动态控制缓存
• 结合路由元信息:在路由配置中通过meta
字段标记需缓存的组件,再通过计算属性动态生成include
值。
// 路由配置
const routes = [
{ path: '/pageA', component: PageA, meta: { keepAlive: true } },
{ path: '/pageB', component: PageB, meta: { keepAlive: false } }
];
// 动态include
<keep-alive :include="cachedComponents">
<router-view></router-view>
</keep-alive>
computed: {
cachedComponents() {
return this.$route.matched
.filter(route => route.meta.keepAlive)
.map(route => route.name);
}
}
此方式通过路由元信息灵活控制缓存。
3. 注意事项
• 组件需设置name
属性:include
通过组件名称匹配,因此被缓存组件必须显式定义name
属性。
• 优先级:若同时存在include
和exclude
,exclude
的优先级更高。例如:
<keep-alive include="A,B" exclude="B">
<component :is="currentComponent"></component>
</keep-alive>
此时仅缓存组件A
,因B
被排除。
4. 生命周期钩子
被缓存的组件会触发activated
(激活时)和deactivated
(停用时)钩子,而非created
或mounted
,需在对应钩子中处理状态更新。
1. <keep-alive>
的生命周期流程
当组件被包裹在 <keep-alive>
内时,其生命周期会分为以下阶段:
阶段 | 触发条件 | 回调钩子 | 行为说明 |
---|---|---|---|
初次进入 | 组件首次被渲染 | created , mounted | 正常初始化,执行逻辑 |
切换至其他组件 | 组件被切换到非活动状态 | deactivated | 停用回调,保存状态或清理资源 |
再次被激活 | 组件重新进入活动状态 | activated | 激活回调,恢复状态或刷新数据 |
组件销毁 | 缓存达到 max 限制或手动销毁 | destroyed | 销毁组件实例,释放内存 |
2. 关键生命周期钩子详解
(1) activated
钩子
• 触发时机:组件从缓存中被重新激活时(例如用户返回到该页面)。
• 典型用途:
• 加载最新数据(例如从服务端获取)。
• 恢复动态修改的 DOM 状态(如滚动位置、定时器)。
• 更新组件内部状态(如重置表单或重新计算数据)。
• 示例:
export default {
activated() {
console.log('组件被激活');
this.fetchData(); // 刷新数据
this.initTimer(); // 重启定时器
},
};
(2) deactivated
钩子
• 触发时机:组件被切换到缓存中(例如用户跳转到其他页面)。
• 典型用途:
• 取消定时器或异步操作,避免内存泄漏。
• 保存当前状态到本地存储或 Vuex。
• 暂停动画或视频播放。
• 示例:
export default {
deactivated() {
console.log('组件被停用');
clearInterval(this.timer); // 清除定时器
this.saveScrollPosition(); // 保存滚动位置
},
};
(3) destroyed
钩子
• 触发时机:当组件被彻底销毁时(例如缓存满后被移除,或调用 $destroy()
)。
• 典型用途:
• 释放强引用资源(如 WebSocket 连接)。
• 清理全局事件监听器。
• 注意:仅在组件被销毁时触发,缓存中的组件不会触发此钩子。
3. 生命周期对比(普通组件 vs <keep-alive>
组件)
钩子 | 普通组件 | <keep-alive> 组件 |
---|---|---|
created | ✅ | ✅(仅第一次初始化时触发) |
mounted | ✅ | ✅(仅第一次初始化时触发) |
updated | ✅ | ✅ |
deactivated | ❌ | ✅(停用时触发) |
activated | ❌ | ✅(激活时触发) |
destroyed | ✅(组件销毁时触发) | ✅(缓存超限或手动销毁时触发) |
4. 实际应用场景
场景 1:页面切换时保留滚动位置
export default {
data() {
return { scrollY: 0 };
},
activated() {
// 恢复滚动位置
window.scrollTo(0, this.scrollY);
},
deactivated() {
// 保存滚动位置
this.scrollY = window.scrollY;
},
};
场景 2:列表页滚动加载数据
export default {
data() {
return { page: 1, loading: false };
},
activated() {
if (!this.loading) {
this.fetchMoreData(); // 刷新数据
}
},
};
5. 注意事项
-
状态管理:
• 缓存组件不会销毁实例,因此需谨慎处理状态(如避免重复请求数据)。
• 推荐结合 Vuex 或本地存储管理全局状态。 -
性能优化:
• 使用max
属性限制缓存数量,避免内存占用过高。
• 在deactivated
中清理不必要的资源(如定时器、事件监听)。 -
组件名匹配:
• 确保被缓存的组件显式声明了name
属性(include/exclude
依赖组件名匹配)。
总结
<keep-alive>
的生命周期机制通过 activated
和 deactivated
钩子,实现了组件状态的暂停与恢复。