1. 概念
keep-alive是vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。它自身并不会渲染成一个DOM元素。
保留状态的含义是:比如当前页面有两个链接,一个是新闻,一个是信息。在该页面展示信息的内容,再切换到其他组件,再切换回来仍显示信息的内容,而不是新闻的内容。
2. 作用
在组件切换过程中将状态保留在内存中,防止重复渲染DOM,提高页面加载性能与用户体验。
3. 原理
在调用created函数时,将需要缓存的VNode节点保存在缓存中,页面渲染时,如果VNode的name符合缓存条件,(Include和exclude属性),就会从缓存中取出之前的VNode实例进行渲染。
VNode:虚拟DOM,其实就是一个JS对象。
4. 属性
它有三个重要的属性:
- include-----字符串或表达式,只有匹配的组件才会被缓存
- exclude-----字符串或表达式,匹配的组件不会被缓存
- max----------数字。最多可以缓存多少组件实例
router-view 也是一个组件,如果直接被包在 keep-alive 里边,所以路径匹配到的视图组件都会被缓存
//Profile,User是组件的名字,name:User。当匹配到这两个组件时,组件不会被缓存,而是频繁的被创建与被销毁,其他的组件会被缓存
<keep-alive exclude='Profile,User'>
<router-view>
所有匹配到的视图组件都会被缓存
</router-view>
</keep-alive>
缺点:需要知道组件的 name,项目复杂的时候不是很好的选择,所以还可以在路由规则中添加meta
属性。
5. 生命周期钩子函数
activated:活跃(显示该组件的时候)
-
deactivated:不活跃(不显示该组件的时候)
只有用了<keep-alive>组件的时候,才会触发这两个生命周期钩子函数,若没有用该组件,即使写了这两个函数也不会触发
使用场景:
created(){
console.log('created')
}
destroyed(){
console.log('destroyed')
}
当组件频繁切换的时候,会在控制台上频繁输出 这两个语句。
- 切换到该组件,控制台输出:
created
- 切出该组件,控制台输出:
destroyed
- 再切入切除,频繁的输出
created
和destroyed
所以可以看出该组件是不断的被创建并销毁的。
当时用keep-alive
,只会创建一次,即时切出该组件,也不会销毁该组件,再进入该组件,也不会创建。
当引入keep-alive
的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入或退出时,只触发activated和deactivated。
注意:
使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来 created 钩子函数中获取数据的任务。
6. 使用示例
-
在App.vue里边
<template> <div id="app"> <keep-alive> <router-view/> </keep-alive> </div> </template> <script> export default { name: 'App' } </script>
根据条件缓存页面
App.vue中
<template>
<div id="app">
// 1. 将缓存 name 为 test 的组件
<keep-alive include='test'>
<router-view/>
</keep-alive>
// 2. 将缓存 name 为 a 或者 b 的组件,结合动态组件使用
<keep-alive include='a,b'>
<router-view/>
</keep-alive>
// 3. 使用正则表达式,需使用 v-bind
<keep-alive :include='/a|b/'>
<router-view/>
</keep-alive>
// 5.动态判断
<keep-alive :include='includedComponents'>
<router-view/>
</keep-alive>
// 5. 将不缓存 name 为 test 的组件
<keep-alive exclude='test'>
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
结合Router,缓存部分页面
- 在 router 目录下的 index.js 文件里
import Vue from 'vue'
import Router from 'vue-router'
const Home = resolve => require(['@/components/home/home'], resolve)
const Goods = resolve => require(['@/components/home/goods'], resolve)
const Ratings = resolve => require(['@/components/home/ratings'], resolve)
const Seller = resolve => require(['@/components/home/seller'], resolve)
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home,
meta: {
keepAlive: true // 需要被缓存
}
}, {
path: '/:id',
name: 'edit',
component: Edit,
meta: {
keepAlive: false // 不需要被缓存
}
}
]
})
- 在 App.vue 里面
<template>
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 这里是会被缓存的视图组件,比如 Home! -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 这里是不被缓存的视图组件,比如 Edit! -->
</router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
优点:不需要例举出需要被缓存组件名称
参考链接: