Code前端首页关于Code前端联系我们

一、keep-alive和include到底是做什么的?

terry 11小时前 阅读数 9 #Vue
文章标签 alive;include

在Vue3项目里做性能优化时,keep-alive的include经常被用来精准控制组件缓存,但不少同学刚开始用总会碰到匹配不上、缓存没生效这些问题,今天就把keep-alive include的用法、场景、避坑点一次性讲清楚~

先搞明白基础概念:keep-alive是Vue3内置的一个组件,它的作用是缓存组件实例——简单说,组件切换时(比如路由跳转、组件切换),被keep-alive包裹的组件不会被销毁,下次再渲染时直接用缓存的实例,不用重新创建、请求数据、渲染DOM,能大幅提升性能。

那include是keep-alive的一个属性,用来筛选哪些组件要被缓存,打个比方:keep-alive像个“仓库”,include就是“准入名单”,只有名字在名单里的组件,仓库才会给它留位置缓存;反之,exclude是“黑名单”,名单里的组件不准缓存(include优先级比exclude高)。

include的基础使用姿势有哪些?

知道是干啥的后,得学会怎么用,include的配置方式主要有三种,而且得和组件的name选项配合好:

字符串形式(单组件缓存)

如果只有一个组件要缓存,直接写组件的name:

<keep-alive include="UserInfo">
  <router-view></router-view>
</keep-alive>

这时候,只有name为UserInfo的组件会被缓存,其他组件走正常销毁-重建流程。

数组形式(多组件缓存)

需要缓存多个组件时,用数组存多个组件name:

<keep-alive :include="['HomePage', 'ArticleList']">
  <router-view></router-view>
</keep-alive>

这里要注意加v-bind(简写),因为数组是动态数据~

正则形式(批量匹配)

如果想按“规则”匹配组件(比如所有以Admin开头的组件),可以用正则:

<keep-alive :include="/^Admin/">
  <router-view></router-view>
</keep-alive>

同样要加v-bind,因为正则是JS表达式,不过实际项目里正则用得少,因为组件name一般是明确的,数组更直观。

关键提醒:不管用哪种形式,组件必须显式声明name!比如用setup语法糖时,得用defineOptions指定name:

<template>...</template>
<script setup>
defineOptions({
  name: 'HomePage' // 必须和include里的名字完全一致
})
</script>

Vue3里用setup语法糖时,默认没有组件name(不像Vue2单文件组件会默认取文件名),所以一定要手动写name,否则include匹配不到!

实际项目里怎么用include优化性能?

光看语法没用,得结合场景,举个最常见的例子:列表页 + 详情页的切换。

比如做一个博客系统,列表页(ArticleList)展示所有文章,点进去是详情页(ArticleDetail),每次从详情页切回列表页时,要是列表页重新渲染,就得重新请求接口、重新渲染表格,很浪费性能,这时候用keep-alive + include缓存列表页就很必要。

步骤拆解:

  1. 给列表页组件加name

    <!-- ArticleList.vue -->
    <template>
    <div class="article-list">
     <!-- 文章列表内容 -->
    </div>
    </template>
    <script setup>
    defineOptions({
    name: 'ArticleList'
    })
    // 这里可以用onActivated和onDeactivated处理缓存前后的逻辑
    import { onActivated, onDeactivated } from 'vue'
    onActivated(() => {
    console.log('列表页被激活,可做局部刷新')
    })
    onDeactivated(() => {
    console.log('列表页被缓存,可保存临时状态')
    })
    </script>
  2. 在布局组件里配置keep-alive
    假设所有页面通过router-view渲染,在App.vue(或布局组件)里包裹:

    <template>
    <div id="app">
     <keep-alive include="ArticleList">
       <router-view></router-view>
     </keep-alive>
    </div>
    </template>

这样,ArticleList组件切换到其他页面(比如ArticleDetail)时,实例会被缓存;切回来时直接用缓存,不用重新请求数据、渲染DOM,性能秒提升~

这些坑踩过才知道要避!

用include时,很多问题都是“细节没注意”导致的,分享几个高频踩坑点:

组件name没配或配错

前面强调过,Vue3用setup语法糖时必须手动写name,但还有个隐蔽问题:name的大小写要完全一致!比如组件name是ArticleList,include里写成articleList(驼峰变小写),就匹配不上,缓存不生效。

动态修改include不生效

如果想根据用户操作动态改缓存名单(比如用户点按钮,新增一个要缓存的组件),直接改普通数组没用,得用响应式数据

<script setup>
import { ref } from 'vue'
const includeList = ref(['ArticleList']) // 用ref包数组,保证响应式
// 点击按钮后新增缓存组件
const addCache = () => {
  includeList.value.push('UserInfo') // 这样修改才会触发keep-alive更新
}
</script>
<template>
  <keep-alive :include="includeList">
    <router-view></router-view>
  </keep-alive>
  <button @click="addCache">新增缓存组件</button>
</template>

如果直接用const includeList = ['ArticleList'](非响应式),修改数组不会触发keep-alive重新计算,缓存逻辑就乱了。

和Vue Router结合时的“元信息”误区

很多同学喜欢在路由元信息(meta)里配keepAlive: true,然后在App.vue里判断:

<keep-alive :include="includeList">
  <router-view v-slot="{ Component, route }">
    <component 
      :is="Component" 
      v-if="route.meta.keepAlive"
    />
    <component 
      :is="Component" 
      v-else
    />
  </router-view>
</keep-alive>

这时候要注意:路由组件的name必须和include里的name一致,而且如果是嵌套路由,子组件的缓存逻辑也得单独处理(比如父组件缓存了,子组件是否要缓存得看自己的name和include)。

Vue3和Vue2在include使用上的区别?

升级Vue3后,很多同学发现之前Vue2的写法突然不生效了,核心区别在组件name的默认行为
  • Vue2:单文件组件(.vue)如果没写name,默认name是文件名的大驼峰形式(比如my-component.vue默认name是MyComponent),所以include很容易匹配。
  • Vue3:用<script setup>语法糖时,默认没有name(组件实例的name是undefined)!必须用defineOptions({ name: 'xxx' })显式声明,否则include根本找不到要缓存的组件。

举个🌰:Vue2里ArticleList.vue不用写name,include="ArticleList"能直接匹配;但Vue3用setup语法糖时,必须手动写defineOptions({ name: 'ArticleList' }),否则include匹配失败。

进阶:结合组合式API更灵活控制缓存

如果项目里有复杂场景(比如不同用户角色缓存不同组件、根据权限动态调整缓存名单),可以用组合式API封装逻辑,让include更智能:

示例:根据用户角色动态生成include列表

<script setup>
import { ref, watch } from 'vue'
import { useUserStore } from '@/stores/user' // 假设用Pinia存用户信息
// 封装组合式API
const useDynamicInclude = () => {
  const userStore = useUserStore()
  const include = ref([])
  // 监听用户角色变化,动态改include
  watch(() => userStore.role, (newRole) => {
    if (newRole === 'admin') {
      include.value = ['AdminDash', 'AdminTable', 'AdminChart']
    } else if (newRole === 'editor') {
      include.value = ['EditorDash', 'ArticleEdit']
    } else {
      include.value = ['UserDash']
    }
  }, { immediate: true }) // 初始化时立即执行
  return { include }
}
const { include } = useDynamicInclude()
</script>
<template>
  <keep-alive :include="include">
    <router-view></router-view>
  </keep-alive>
</template>

这样不管是管理员、编辑还是普通用户,切换角色时缓存名单自动更新,不用在模板里写一堆判断,代码更简洁易维护~

Vue3里用keep-alive include要记住这几点:明确组件name、用响应式数据控制动态名单、结合场景避坑(尤其是Vue3和Vue2的name差异),把这些搞懂后,不管是列表页缓存、多角色权限适配,还是复杂路由场景,都能精准控制组件缓存,让项目性能起飞~要是你还有其他关于keep-alive的疑问,评论区随时聊~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门