請(qǐng)闡述keep-alive組件的作用和原理

?? keep-alive 作用
keep-live組件是vue的內(nèi)部組件,主要用于緩存內(nèi)部組件實(shí)例。這樣做的目的在于keep-alive內(nèi)部組件切換時(shí),不需要重新創(chuàng)建組件實(shí)例,比如說(shuō)使用v-if來(lái)決定在滿足什么條件下使用哪個(gè)組件,還有就是路由切換,有個(gè)<router-view></router-view>,它會(huì)根據(jù)路由的配置,將選擇其中一個(gè)組件渲染到這個(gè)位置,當(dāng)路由切換后,當(dāng)前組件銷毀,它又會(huì)渲染另一個(gè)組件。
如果將keep-alive嵌套在最外層,就像這樣:
<keepAlive>
<Component1 v-if="xxx"/>
<Component2 v-else-if="xxx"/>
<Component1 v-else/>
</KeepAlive>
這樣keepAlive內(nèi)部的組件來(lái)回切換時(shí),就不需要重新創(chuàng)建組件實(shí)例,而是直接使用緩存中的實(shí)例,一方面可以避免創(chuàng)建組件帶來(lái)的效率開(kāi)銷,另一方面可以保留組件的狀態(tài)。但同時(shí)也有不好的地方,就是當(dāng)組件里面包含大量的內(nèi)容的時(shí)候會(huì)占用更多的內(nèi)存空間,keepAlive相當(dāng)于是空間換時(shí)間的做法。
keepAlive有include和exclude屬性,這兩個(gè)屬性決定哪些組件可以進(jìn)入緩存。另外還有一個(gè)max屬性,通過(guò)它可以設(shè)置最大緩存數(shù),當(dāng)緩存的實(shí)例超過(guò)設(shè)置的數(shù)時(shí),vue會(huì)移除最久沒(méi)有使用的組件緩存。
受keep-alive的影響,其內(nèi)部所有嵌套的組件都具有兩個(gè)生命周期鉤子函數(shù),分別是activated和deactivated,它們分別在組件激活和失活的時(shí)候觸發(fā),第一次activated觸發(fā)是在mounted之后
?? keep-alive 原理
在具體實(shí)現(xiàn)上,keep-alive在內(nèi)部維護(hù)了一個(gè)key數(shù)組和一個(gè)緩存對(duì)象
//keep-alive 內(nèi)部聲明周期函數(shù)
created () {
this.cache = Object.create(null)
this.keys = []
},
key數(shù)組記錄目前緩存的組件key值,如果組件沒(méi)有指定key值,會(huì)自動(dòng)生成一個(gè)唯一的key值
cache對(duì)象會(huì)以key值為鍵,vnode為值,用于緩存組件對(duì)應(yīng)的虛擬DOM
在keep-alive的渲染函數(shù)中,其基本邏輯是判斷當(dāng)前渲染的vnode是否有對(duì)應(yīng)的緩存,如果有,會(huì)從緩存中讀取到對(duì)應(yīng)的組件實(shí)例,如果沒(méi)有就會(huì)把它緩存。
當(dāng)緩存的數(shù)量超過(guò)max設(shè)置的數(shù)值時(shí),keep-alive會(huì)移除key數(shù)組中的第一個(gè)元素
render () {
const slot = this.$slots.default; //獲取默認(rèn)插槽
const vnode = getFirstComponentChild(slot); //得到插槽中第一個(gè)組件的vnode
const name = getComponentName(vnode.componentOptions); //獲取組件名字
const { cache, keys } = this; //獲取當(dāng)前的混村內(nèi)對(duì)象和key數(shù)組
const key: ?string = vnode.key == null
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key; //獲取組件的key值,如果沒(méi)有key值,會(huì)按照規(guī)則自動(dòng)生成
if (cache[key]) {
//有緩存
//重用組件實(shí)例
vnode.componentInstance = cache[key].componentInstance
remove(keys, key); //刪除key值
//將key值加入到數(shù)組末尾,這樣是為了保證最近使用的組件在數(shù)組中靠后,主要是為了方便設(shè)置的max值刪除很久沒(méi)使用的組件
keys.push(key)
} else {
//沒(méi)有緩存的則進(jìn)行緩存
cache[key] = vnode
keys.push(key)
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
//超過(guò)最大緩存數(shù)量,移除第一個(gè)key對(duì)應(yīng)的緩存
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
?? 好了, 以上就是我的分享,歡迎大家在評(píng)論區(qū)討論鴨~
希望小伙伴們點(diǎn)贊 ?? 支持一下哦~ ??,我會(huì)更有動(dòng)力的 ??
