大部分的Vue應用都采用spa模式開發,進而達到一次加載,全站使用的目的,可以極大地提高應用的使用者體驗。而spa應用的原理其實就是動态的把目标頁面的代碼替換到路由元件内,進而實作路由切換的目的。那麼,問題來了,加入我有頁面A、頁面B兩個頁面,頁面A中有一堆表單,使用者填了一半,然後切換到B頁面去看一個消息,看完想要回到頁面A繼續填寫表單,如果不經任何處理的話,使用者回到頁面A的結果隻有一個,自己辛辛苦苦填了老半天的表單資料都被清空了,又得重新填寫。
顯然,這是一個極差的使用者體驗,不過别擔心,Vue已經為我們考慮了這個問題,它已經為我們提供了一個内置元件keep-alive元件,隻要按照要求使用keep-alive元件,當你從頁面A切換到頁面B時,keep-alive會幫你吧頁面A已經輸入的一些資料緩存下來,當你再從頁面B回到頁面A時,表單的資料便可以自動回填,進而讓使用者可以繼續自己未完成的表單填寫。
那麼,keep-alive元件究竟是如何工作的呢?我們來一起看看吧。
節選自Vue源碼中的src/core/components/keep-alive.js
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 () {
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
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
// make current key freshest
remove(keys, key)
keys.push(key)
} else {
cache[key] = vnode
keys.push(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])
}
從Vue源碼可以看出,當頁面元件觸發了destroy生命周期時,keep-alive會将目前元件緩存到一個緩存對象當中,然後才進行頁面跳轉,當頁面重新切換回頁面A時,keep-alive會先看看緩存中是否存在目前元件的緩存資料,如果存在,便會把資料重新回填至該元件中,由于頁面上的表單都采用雙向綁定,元件中的初始值被填充為緩存的值時,表單自然也會恢複回頁面跳轉出去前的樣子,這樣就實作了讓頁面元件緩存與恢複緩存資料的邏輯了
PS:以上為本人在學習Vue源碼時個人的學習感想與記錄,如有不妥,歡迎指正。