vue2中缓存组件keep-alive的使用,附详细案例

在 Vue.js 2 中, 是一个内置组件,用于缓存动态组件或组件的状态,避免重复渲染和销毁,从而提升性能。以下是关于它的核心知识点和使用方法:


作用

  1. 缓存组件:被包裹的组件在切换时不会被销毁,而是保留在内存中。
  2. 保留状态:组件的状态(如数据、DOM 滚动位置等)在切换后依然存在。
  3. 性能优化:减少重复渲染的开销,适合缓存频繁切换但需要保持状态的组件(如 Tab 页、表单输入等)。

基本用法

包裹动态组件或路由组件:

<template>
  
  <keep-alive>
    <component :is="currentComponent">component>
  keep-alive>

  
  <keep-alive>
    <router-view>router-view>
  keep-alive>
template>

name说明

  1. name 必须唯一且准确

    • includeexclude 的值需与组件的 name 完全一致(区分大小写),比如:name: "UserProfile",但 include="userprofile" 会导致匹配失败,无法缓存。
      // UserProfile .vue
      export default{
        name:"UserProfile ",  //  include 和 exclude的值就是vue组件的名称(name)
        data(){
        	return {}
        }
      }
      
      
  2. 动态组件的 name

    • 如果是缓存动态组件,确保vue文件的 name 属性已正确设置,且已引入需要缓存的组件,请看示例4
  3. 路由组件的 name

    • 如果通过 Vue Router 使用 ,路由组件的 name 是组件自身的 name,而非路由配置中的 name 字段,请看示例2
      // router.js
      {
        path: '/user',
        name: 'user-route', // 这是路由的 name,和组件无关!
        component: UserProfile // 组件内部的 name 是 'UserProfile'
      }
      

常用属性

  1. include
    • 类型String | RegExp | Array
    • 说明:只有名称匹配的组件会被缓存,可以接受 字符串、正则表达式或数组 作为参数,匹配组件的 name 选项,区分大小写(默认行为,但可以通过正则表达式忽略大小写)。

使用:

示例1:缓存路由组件——数组形式

 <template>
	 <div>
 	 	 
 		 <keep-alive :include="cachedViews">
 			  <router-view/>
 		 keep-alive>
 	 div>	
template>

<script>
export default {
  data() {
    return {};
  },
  computed: {
  	// 在进行路由切换时,使用vuex存储组件的名称,怎么使用vuex,不在此详细说明
 	 cachedViews() {
        return this.$store.state.tagsView.cachedViews
      },
  }
};
script>

示例2:缓存路由组件——字符串形式

 <template>
	 <div>
 	 	 
 		 <keep-alive :include="cachedViews">
 			  <router-view/>
 		 keep-alive>
 	 div>	
template>

<script>
export default {
  data() {
    return {
      cachedViews:"UserProfile,Settings"
    };
  },
  computed: {
  	// 也可使用vuex进行存储,请看示例1
  }
};
script>
   // 被缓存的文件 UserProfile.vue
   export default{
   	name:"UserProfile",  
   	data(){
   		return {}
   	}
   }

  // 路由文件router.js
  {
    path: '/userSys',
    name: 'userFile, 
    component: () => import('@/views/user/index.vue')
  }

示例3:缓存路由组件——正则表达式形式

 <template>
	 <div>
 	 	 
 		 <keep-alive :include="cachedViews">
 			  <router-view/>
 		 keep-alive>
 	 div>	
template>

<script>
export default {
  data() {
    return {
    // 缓存名称为sys开头的组件
      regular :"/^sys[A-Z]/" 
    };
  },
};
script>

示例4:缓存动态组件component ——数组形式

 
 <template>
	 <div>
 	 	 
 		 <keep-alive :include="cachedViews">
 			   <component :is="currentComponent"  style="height: 100%">component>
 		 keep-alive>
 	 div>	
template>

<script>
import sysClassify from "@/views/sysClassify/index.vue";
import sysSignature from "@/views/sysSignature/index.vue";
import sysType from "@/views/sysType/index.vue";

export default {
  components: {sysClass, sysSignature,sysType},
    computed: {
         // 从store中获取组要缓存的组件名称
   		 cachedViews() {
      		return this.$store.state.tagsView.cachedViews
   		  },
   		  // 使用组件名称当做组件名字
   		 currentComponent(){
      		return this.$route.name
    	  }
  },
};
script>
   // 被缓存的文件路径 sysClassify/index.vue
   export default{
   	name:"sysClassify",  
   	data(){
   		return {}
   	}
   }

  // 路由文件router.js
  {
    path: '/userSys',
    name: 'sysClassify, // 此时的路由name和vue文件中的name相同,所以能在动态组件中直接使用$route.name当做
    component: () => import('@/views/sysClassify/index.vue')
  }

这里为什么使用能用路由名称呢?
答:因为在项目中设置了路由的名称和vue文件的名称相同
为什么要在component组件中添加高度呢?
答:也可以不在component组件中设置高度,但是需要在缓存的动态组件中最外层标签中设置也可以,否则会造成不确定的问题,比如,高度不停增加

示例5:缓存动态组件——字符串形式

<template>
 <div>
   <button @click="toggleComponent('ComponentA')">切换 Abutton>
   <button @click="toggleComponent('ComponentB')">切换 Bbutton>

   <keep-alive :include="cachedComponents">
     <component :is="currentComponent">component>
   keep-alive>
 div>
template>

<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

export default {
 components: { ComponentA, ComponentB },
 data() {
   return {
     currentComponent: 'ComponentA',
     cachedComponents: "ComponentA,ComponentB" // 不能有空格
   };
 },
 methods: {
   toggleComponent(name) {
     this.currentComponent = name;
   },
 }
};
script>
  1. exclude

    • 类型String | RegExp | Array
    • 说明:名称匹配的组件会被缓存。 同样接受 字符串正则表达式或数组 作为参数。优先级高于 include(若同时使用,以 exclude 为准)。
    • 示例
      同include属性一样,具体案例看include的示例
      
  2. max

    • 类型Number
    • 作用:最多缓存的组件实例数量,超出时销毁最久未访问的实例。
    • 示例
      <keep-alive :max="5">
        <router-view>router-view>
      keep-alive>
      

总结

属性 作用 值类型 优先级
include 缓存匹配的组件 String / RegExp / Array
exclude 不缓存匹配的组件 String / RegExp / Array

生命周期钩子

被缓存的组件会触发以下钩子函数:

  • activated:组件被激活时调用(首次渲染或从缓存中恢复)。
  • deactivated:组件被停用时调用(切换出缓存)。
export default {
  activated() {
    console.log('组件激活,可重新获取数据');
  },
  deactivated() {
    console.log('组件停用,可清理定时器等');
  }
}

注意事项

  1. 组件必须命名includeexclude 依赖组件的 name 选项,确保组件已定义 name
  2. 动态组件限制 只能包裹一个动态组件()或路由视图()。
  3. 路由缓存策略:若需缓存特定路由,可在路由配置中通过 meta 字段标记:
    // router.js
    {
      path: '/pageA',
      component: PageA,
      meta: { keepAlive: true }
    }
    
    然后在组件中动态控制:
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive">router-view>
    keep-alive>
    <router-view v-if="!$route.meta.keepAlive">router-view>
    

常见问题

  • 缓存失效:检查组件 name 是否正确,或 include/exclude 是否匹配。
  • 内存占用:合理使用 max 属性限制缓存数量。
  • 数据更新:在 activated 中刷新数据,避免使用旧数据。

你可能感兴趣的:(vue知识,vue.js,前端,缓存)