vue.js內(nèi)置組件之keep-alive組件使用
keep-alive是Vue.js的一個內(nèi)置組件。<keep-alive> 包裹動態(tài)組件時,會緩存不活動的組件實例,而不是銷毀它們。它自身不會渲染一個 DOM 元素,也不會出現(xiàn)在父組件鏈中。 當(dāng)組件在 <keep-alive> 內(nèi)被切換,它的 activated 和 deactivated 這兩個生命周期鉤子函數(shù)將會被對應(yīng)執(zhí)行。 它提供了include與exclude兩個屬性,允許組件有條件地進行緩存。
舉個栗子
<keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></router-view>

在點擊button時候,兩個input會發(fā)生切換,但是這時候這兩個輸入框的狀態(tài)會被緩存起來,input標(biāo)簽中的內(nèi)容不會因為組件的切換而消失。
* include - 字符串或正則表達式。只有匹配的組件會被緩存。
* exclude - 字符串或正則表達式。任何匹配的組件都不會被緩存。
<keep-alive include="a"> <component></component> </keep-alive>
只緩存組件別民name為a的組件
<keep-alive exclude="a"> <component></component> </keep-alive>
除了name為a的組件,其他都緩存下來
生命周期鉤子
生命鉤子 keep-alive提供了兩個生命鉤子,分別是activated與deactivated。
因為keep-alive會將組件保存在內(nèi)存中,并不會銷毀以及重新創(chuàng)建,所以不會重新調(diào)用組件的created等方法,需要用activated與deactivated這兩個生命鉤子來得知當(dāng)前組件是否處于活動狀態(tài)。
深入keep-alive組件實現(xiàn)
查看vue--keep-alive組件源代碼可以得到以下信息
created鉤子會創(chuàng)建一個cache對象,用來作為緩存容器,保存vnode節(jié)點。
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
created () {
// 創(chuàng)建緩存對象
this.cache = Object.create(null)
// 創(chuàng)建一個key別名數(shù)組(組件name)
this.keys = []
},
destroyed鉤子則在組件被銷毀的時候清除cache緩存中的所有組件實例。
destroyed () {
/* 遍歷銷毀所有緩存的組件實例*/
for (const key in this.cache) {
pruneCacheEntry(this.cache, key, this.keys)
}
},
:::demo
render () {
/* 獲取插槽 */
const slot = this.$slots.default
/* 根據(jù)插槽獲取第一個組件組件 */
const vnode: VNode = getFirstComponentChild(slot)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
// 獲取組件的名稱(是否設(shè)置了組件名稱name,沒有則返回組件標(biāo)簽名稱)
const name: ?string = getComponentName(componentOptions)
// 解構(gòu)對象賦值常量
const { include, exclude } = this
if ( /* name不在inlcude中或者在exlude中則直接返回vnode */
// 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]) { // 判斷當(dāng)前是否有緩存,有則取緩存的實例,無則進行緩存
vnode.componentInstance = cache[key].componentInstance
// make current key freshest
remove(keys, key)
keys.push(key)
} else {
cache[key] = vnode
keys.push(key)
// 判斷是否設(shè)置了最大緩存實例數(shù)量,超過則刪除最老的數(shù)據(jù),
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
// 給vnode打上緩存標(biāo)記
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
// 銷毀實例
function pruneCacheEntry (
cache: VNodeCache,
key: string,
keys: Array<string>,
current?: VNode
) {
const cached = cache[key]
if (cached && (!current || cached.tag !== current.tag)) {
cached.componentInstance.$destroy()
}
cache[key] = null
remove(keys, key)
}
// 緩存
function pruneCache (keepAliveInstance: any, filter: Function) {
const { cache, keys, _vnode } = keepAliveInstance
for (const key in cache) {
const cachedNode: ?VNode = cache[key]
if (cachedNode) {
const name: ?string = getComponentName(cachedNode.componentOptions)
// 組件name 不符合filler條件, 銷毀實例,移除cahe
if (name && !filter(name)) {
pruneCacheEntry(cache, key, keys, _vnode)
}
}
}
}
// 篩選過濾函數(shù)
function matches (pattern: string | RegExp | Array<string>, name: string): boolean {
if (Array.isArray(pattern)) {
return pattern.indexOf(name) > -1
} else if (typeof pattern === 'string') {
return pattern.split(',').indexOf(name) > -1
} else if (isRegExp(pattern)) {
return pattern.test(name)
}
/* istanbul ignore next */
return false
}
// 檢測 include 和 exclude 數(shù)據(jù)的變化,實時寫入讀取緩存或者刪除
mounted () {
this.$watch('include', val => {
pruneCache(this, name => matches(val, name))
})
this.$watch('exclude', val => {
pruneCache(this, name => !matches(val, name))
})
},
:::
通過查看Vue源碼可以看出,keep-alive默認傳遞3個屬性,include 、exclude、max, max 最大可緩存的長度
結(jié)合源碼我們可以實現(xiàn)一個可配置緩存的router-view
<!--exclude - 字符串或正則表達式。任何匹配的組件都不會被緩存。--> <!--TODO 匹配首先檢查組件自身的 name 選項,如果 name 選項不可用,則匹配它的局部注冊名稱--> <keep-alive :exclude="keepAliveConf.value"> <router-view class="child-view" :key="$route.fullPath"></router-view> </keep-alive> <!-- 或者 --> <keep-alive :include="keepAliveConf.value"> <router-view class="child-view" :key="$route.fullPath"></router-view> </keep-alive> <!-- 具體使用 include 還是exclude 根據(jù)項目是否需要緩存的頁面數(shù)量多少來決定-->
創(chuàng)建一個keepAliveConf.js 放置需要匹配的組件名
// 路由組件命名集合
var arr = ['component1', 'component2'];
export default {value: routeList.join()};
配置重置緩存的全局方法
import keepAliveConf from 'keepAliveConf.js'
Vue.mixin({
methods: {
// 傳入需要重置的組件名字
resetKeepAive(name) {
const conf = keepAliveConf.value;
let arr = keepAliveConf.value.split(',');
if (name && typeof name === 'string') {
let i = arr.indexOf(name);
if (i > -1) {
arr.splice(i, 1);
keepAliveConf.value = arr.join();
setTimeout(() => {
keepAliveConf.value = conf
}, 500);
}
}
},
}
})
在合適的時機調(diào)用調(diào)用this.resetKeepAive(name),觸發(fā)keep-alive銷毀組件實例;

Vue.js內(nèi)部將DOM節(jié)點抽象成了一個個的VNode節(jié)點,keep-alive組件的緩存也是基于VNode節(jié)點的而不是直接存儲DOM結(jié)構(gòu)。它將滿足條件的組件在cache對象中緩存起來,在需要重新渲染的時候再將vnode節(jié)點從cache對象中取出并渲染。
總結(jié)
以上所述是小編給大家介紹的vue.js內(nèi)置組件之keep-alive組件使用,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
vue.js實現(xiàn)數(shù)據(jù)動態(tài)響應(yīng) Vue.set的簡單應(yīng)用
這篇文章主要介紹了vue.js實現(xiàn)數(shù)據(jù)動態(tài)響應(yīng),Vue.set的簡單應(yīng)用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
vue?中使用?this?更新數(shù)據(jù)的一次問題記錄
這篇文章主要介紹了vue?中使用?this?更新數(shù)據(jù)的一次大坑?,我在 vue 實例中聲明了一個數(shù)組屬性如?books: [],在異步請求的回調(diào)函數(shù)中使用?this.books = res.data.data;?進行數(shù)據(jù)更新,感興趣的朋友跟隨小編一起看看吧2022-11-11
vue自定義密碼輸入框解決瀏覽器自動填充密碼的問題(最新方法)
這篇文章主要介紹了vue自定義密碼輸入框解決瀏覽器自動填充密碼的問題,通過將密碼輸入框的type設(shè)置為text,修改樣式上的顯示,來實現(xiàn)既可以讓瀏覽器不自動填充密碼,又可以隱藏密碼的效果,需要的朋友可以參考下2023-04-04
crypto-js對稱加密解密的使用方式詳解(vue與java端)
這篇文章主要介紹了如何在Vue前端和Java后端使用crypto-js庫進行AES加密和解密,前端通過創(chuàng)建AES.js文件來實現(xiàn)加密解密功能,并在Vue文件或JavaScript中使用,后端則可以直接使用Java代碼進行AES加密和解密操作,需要的朋友可以參考下2025-01-01

