這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰node
keep-alive 是 Vue 內置的一個抽象組件,可使被包含的組件保留狀態,即keep-alive 能夠實現組件的緩存,當組件切換時不會對當前組件進行卸載。正則表達式
在組件切換過程當中將狀態保留在內存中,防止重複渲染DOM,減小加載時間及性能消耗,提升用戶體驗性。緩存
通常結合路由和動態組件一塊兒使用,用於緩存組件;markdown
提供 include 和 exclude 屬性,二者都支持字符串或正則表達式, include 表示只有名稱匹配的組件會被緩存,exclude 表示任何名稱匹配的組件都不會被緩存 ,其中 exclude 的優先級比 include 高;函數
對應兩個鉤子函數 activated 和 deactivated ,當組件被激活時,觸發鉤子函數 activated,當組件被移除時,觸發鉤子函數 deactivated。post
props:性能
- include - 字符串或正則表達式。只有名稱匹配的組件會被緩存。
- exclude - 字符串或正則表達式。任何名稱匹配的組件都不會被緩存。
- max - 數字。最多能夠緩存多少組件實例。
include和exclude屬性是根據組件中的name屬性來進行過濾的,而非路由中的name
複製代碼
在 created 函數調用時將須要緩存的 VNode 節點保存在 this.cache 中/在 render(頁面渲染) 時,若是 VNode 的 name 符合緩存條件(能夠用 include 以及 exclude 控制),則會從 this.cache 中取出以前緩存的 VNode 實例進行渲染。ui
源碼:core/components/keep-alive.js
this
export default {
name: 'keep-alive',
abstract: true, // 抽象組件
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
created() {
this.cache = Object.create(null) // 建立緩存列表
this.keys = [] // 建立緩存組件的key列表
},
destroyed() { // keep-alive銷燬時 會清空全部的緩存和key
for (const key in this.cache) { // 循環銷燬
pruneCacheEntry(this.cache, key, this.keys)
}
},
mounted() { // 會監控include 和 exclude屬性 進行組件的緩存處理
this.$watch('include', val => {
pruneCache(this, name => matches(val, name))
}) this.$watch('exclude', val => {
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
if ( // 判斷是否緩存
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))) {
return vnode
}
const {
cache,
keys
} = this
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, // 若是組件沒key 就本身經過 組件的標籤和key和cid 拼接一個key
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance // 直接拿到組件實 例
// make current key freshest
remove(keys, key) // 刪除當前的 [b,c,d,e,a]
// LRU 最近最久未使用法
keys.push(key) // 並將key放到後面[b,a]
} else {
cache[key] = vnode // 緩存vnode
keys.push(key) // 將key 存入
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
// 緩存的太多超過了max 就須要刪除掉
pruneCacheEntry(cache, keys[0], keys, this._vnode)
// 要刪除第0個 可是現 在渲染的就是第0個
}
}
vnode.data.keepAlive = true // 而且標準keep-alive下的組件是一個緩存組件
}
return vnode || (slot && slot[0]) // 返回當前的虛擬節點
}
}
``
複製代碼