Vue 中 keep-alive 组件的生命周期钩子

Vue 中 keep-alive 组件的生命周期钩子

本文来自于我关于 Vue生命周期钩子 的系列文章。欢迎阅读、点评与交流~
1、Vue 中的生命周期钩子
2、Vue 中 keep-alive 组件的生命周期钩子

1. keep-alive 组件概述

keep-alive 是 Vue 的内置组件,用于缓存不活动的组件实例,而不是销毁它们。这样可以:

  • 保留组件状态,避免重新渲染
  • 提高应用性能
  • 减少重复的 DOM 操作

2. 基本用法

vue 复制代码
<template>
  <div>
    <keep-alive>
      <component :is="currentComponent"></component>
    </keep-alive>
  </div>
</template>

3. 专门的生命周期钩子

keep-alive 包裹的组件会获得两个额外的生命周期钩子:

activated

  • 调用时机:组件被激活(从缓存中取出并插入到 DOM 中)时调用
  • 使用场景:重新获取数据、开启定时器、重新绑定事件等

deactivated

  • 调用时机:组件被停用(从 DOM 中移除并存入缓存)时调用
  • 使用场景:清除定时器、取消事件监听、释放资源等

4. 完整生命周期执行顺序

首次加载

javascript 复制代码
// 组件第一次进入时
created() → mounted() → activated()

切换到其他组件(当前组件被缓存)

javascript 复制代码
// 当前组件被离开
deactivated()

再次切换回来

javascript 复制代码
// 再次进入缓存的组件
activated()

组件被销毁(当离开路由或 keep-alive 被移除)

javascript 复制代码
// 如果是直接离开路由
deactivated() → beforeDestroy() → destroyed()

// 注意:如果组件被 keep-alive 缓存,则不会触发 beforeDestroy 和 destroyed

5. 实际示例

vue 复制代码
<template>
  <div>
    <button @click="toggle">切换组件</button>
    <keep-alive>
      <ComponentA v-if="showA" />
      <ComponentB v-else />
    </keep-alive>
  </div>
</template>

<script>
// ComponentA.vue
export default {
  name: 'ComponentA',
  data() {
    return {
      timer: null,
      count: 0
    }
  },
  
  created() {
    console.log('ComponentA created')
  },
  
  mounted() {
    console.log('ComponentA mounted')
  },
  
  activated() {
    console.log('ComponentA activated')
    // 重新开启定时器
    this.timer = setInterval(() => {
      this.count++
      console.log('定时器运行中:', this.count)
    }, 1000)
  },
  
  deactivated() {
    console.log('ComponentA deactivated')
    // 清除定时器
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
    }
  },
  
  beforeDestroy() {
    console.log('ComponentA beforeDestroy')
  },
  
  destroyed() {
    console.log('ComponentA destroyed')
  }
}
</script>

6. keep-alive 的属性配置

vue 复制代码
<!-- 只缓存特定组件 -->
<keep-alive include="ComponentA,ComponentB">
  <component :is="currentComponent"></component>
</keep-alive>

<!-- 排除某些组件 -->
<keep-alive exclude="ComponentC">
  <component :is="currentComponent"></component>
</keep-alive>

<!-- 使用正则表达式 -->
<keep-alive :include="/ComponentA|ComponentB/">
  <component :is="currentComponent"></component>
</keep-alive>

<!-- 限制最大缓存实例数 -->
<keep-alive :max="5">
  <component :is="currentComponent"></component>
</keep-alive>

7. 与 Vue Router 结合使用

javascript 复制代码
// router.js
const routes = [
  {
    path: '/page1',
    component: Page1,
    meta: {
      keepAlive: true  // 需要缓存
    }
  },
  {
    path: '/page2',
    component: Page2,
    meta: {
      keepAlive: false // 不需要缓存
    }
  }
]
vue 复制代码
<!-- App.vue -->
<template>
  <div id="app">
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

8. 注意事项和最佳实践

注意事项:

  1. name 属性必需 :组件必须有 name 选项才能被 include/exclude 匹配
  2. 嵌套 keep-alive:Vue 2.2.0+ 支持嵌套使用,但应避免过度使用
  3. 动态组件 :与 <component :is="..."> 结合时最有用
  4. 内存管理 :注意内存泄漏,及时在 deactivated 中清理资源

最佳实践:

javascript 复制代码
export default {
  name: 'MyComponent', // 必须设置 name
  data() {
    return {
      // 数据会被缓存
    }
  },
  activated() {
    // 可以在这里重新获取可能需要更新的数据
    if (this.needsRefresh) {
      this.fetchData()
    }
  },
  deactivated() {
    // 清理工作
    this.cancelPendingRequests()
    clearInterval(this.timer)
  },
  methods: {
    // 如果需要刷新数据的逻辑
    fetchData() {
      // 获取数据
    },
    cancelPendingRequests() {
      // 取消未完成的请求
    }
  }
}

9. Vue 3 中的变化

在 Vue 3 中,keep-alive 的用法基本保持不变,但生命周期钩子名称有变化:

javascript 复制代码
// Vue 3 Composition API
import { onActivated, onDeactivated } from 'vue'

export default {
  setup() {
    onActivated(() => {
      console.log('组件被激活')
    })
    
    onDeactivated(() => {
      console.log('组件被停用')
    })
  }
}

总结

keep-alive 组件的生命周期钩子 activateddeactivated 为缓存组件提供了精确的控制能力。合理使用这些钩子可以有效管理组件状态、优化性能,同时避免内存泄漏等问题。在实际开发中,结合路由配置和动态组件,可以创建出体验更流畅的单页应用。

相关推荐
daols882 小时前
vue2 表格如何使用 vxe-table 带列头复制单元格内容同步到 excel 中
vue.js·excel·vxe-table
晚霞的不甘2 小时前
Flutter for OpenHarmony 布局核心:Row 与 Column 深度解析与实战
android·前端·javascript·flutter
Mr__Miss2 小时前
JMM中的工作内存实际存在吗?
java·前端·spring
huangql5202 小时前
【图文讲解】JavaScript二进制数据处理:从内存到类型化视图
前端
xiaozenbin2 小时前
关于tomcat9页面部分乱码的处理
前端·tomcat·firefox
ethan.Yin2 小时前
element-plus 二次封装遇到的一点疑惑
javascript·vue.js·ecmascript
Ulyanov2 小时前
Impress.js 3D立方体旋转个人年终总结设计与实现
开发语言·前端·javascript·3d·gui开发
榴莲不好吃2 小时前
前端js图片压缩
开发语言·前端·javascript
切糕师学AI2 小时前
Vue 中的 keep-alive 组件
前端·javascript·vue.js