Vue之keep-alive原理

keep-alive是什么?

keep-alive是Vue的一个内置组件,用来缓存keep-alive内节点,当下次在访问的时候会命中缓存,降低请求数量及防止重复渲染dom。接受三个属性,include,exclude,max。
keep-alive是一个抽象组件,根据abstract: true判断:其节点不会渲染到页面中。
含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated

  1. activated 当 keepalive 包含的组件再次渲染的时候触发
  2. deactivated 当 keepalive 包含的组件销毁的时候触发

keep-alive源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
export default {
name: 'keep-alive',
abstract: true,

props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},

created () {
this.cache = Object.create(null) //创建一个缓存的空对象
this.keys = []
},

destroyed () {
for (const key in this.cache) {
// 销毁所有组件
pruneCacheEntry(this.cache, key, this.keys)
}
},

mounted () {
//监听 include 数据是否有变化
this.$watch('include', val => {
//判断include 对象中 name 不存在了 就 调用 检测缓存中的组件,如果不是当前激活的组件则销毁
pruneCache(this, name => matches(val, name))
})
//监听 exclude 数据是否有变化
this.$watch('exclude', val => {
//如果exclude 对象中存在name 不存在了 就 调用 检测缓存中的组件,如果不是当前激活的组件则销毁
pruneCache(this, name => !matches(val, name))
})
},

render () {

const slot = this.$slots.default //获取插槽
const vnode: VNode = getFirstComponentChild(slot) // 获取插槽子组件
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions //获取组件参数
if (componentOptions) {
// check pattern
const name: ?string = getComponentName(componentOptions) //获取组件名称
const { include, exclude } = this //获取include exclude
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}

const { cache, keys } = this //缓存的对象、keys
const key: ?string = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
if (cache[key]) { //获取值 如果key存在
vnode.componentInstance = cache[key].componentInstance //直接获取组件实例化
// make current key freshest
remove(keys, key) //把key添加到末端
keys.push(key)
} else {
//将虚拟dom缓存起来
cache[key] = vnode
keys.push(key) //key缓存起来
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}

vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
}

https://juejin.im/post/6844903837770203144