Vue3?KeepAlive實現(xiàn)原理解析
思路
首先我們知道 KeepAlive 是一個內(nèi)置組件,那封裝一個組件對于大家來說應(yīng)該不會有太大的困難,它的核心邏輯在于它的 render 函數(shù),它用 map 去記錄要緩存的組件,就是 [key,vnode] 的形式。它的核心思想就是 LRU,當我們限制有 maxSize 的時候,超過 maxSize 時我們會刪除最久沒有使用的[key, vnode],可以看看 leetcode146.LRU緩存;基本上你理清了 LRU 算法的思路,keepalive 的原理你也知道的差不多了。
代碼解析
我只貼出來能幫助大家理解的核心代碼,源碼位于core/package/runtime-core/src/components/KeepAlive.ts
setup
const cache: Cache = new Map()
const keys: Keys = new Set()
// cache sub tree after render
let pendingCacheKey: CacheKey | null = null
const cacheSubtree = () => {
// fix #1621, the pendingCacheKey could be 0
if (pendingCacheKey != null) {
cache.set(pendingCacheKey, getInnerChild(instance.subTree))
}
}
// 組件掛載和更新的時候就會緩存最新的組件
onMounted(cacheSubtree)
onUpdated(cacheSubtree)render
tips:這塊邏輯就是 setup 的返回值
const comp = vnode.type as ConcreteComponent
const key = vnode.key == null ? comp : vnode.key
pendingCacheKey = key
const cachedVNode = cache.get(key)
// tips: keys 僅僅是用于收集組件的 key 組件實際收集在cache中
if (cachedVNode) { // 節(jié)點存在緩存中
// copy over mounted state(復(fù)制過去的狀態(tài))
vnode.el = cachedVNode.el
vnode.component = cachedVNode.component
// 將節(jié)點放到隊尾
keys.delete(key)
keys.add(key)
} else { // 不存在
keys.add(key) // 加入緩存隊列
// prune oldest entry
// 超過最大值了,將最久沒有使用的組件刪除,也就是隊頭組件
if (max && keys.size > parseInt(max as string, 10)) {
pruneCacheEntry(keys.values().next().value)
}
}onActivated 和 onDeactived調(diào)用
tips:這兩塊邏輯是在 diff 中,看不懂沒關(guān)系,只要注意一個點就是被緩存的組件節(jié)點有一個標識 ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE,我們在掛載組件的時候和卸載組件的時候判斷一下是否有這個標識,有就去調(diào)用 onActiveated 或 onDeactived;源碼位于:core/package/runtime-core/src/renderer
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
return
}
if (
initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE ||
(parent &&
isAsyncWrapper(parent.vnode) &&
parent.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE)
) {
instance.a && queuePostRenderEffect(instance.a, parentSuspense)
if (
__COMPAT__ &&
isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
) {
queuePostRenderEffect(
() => instance.emit('hook:activated'),
parentSuspense
)
}
}到此這篇關(guān)于Vue3 KeepAlive實現(xiàn)原理的文章就介紹到這了,更多相關(guān)Vue3 KeepAlive原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Vue調(diào)取接口,并渲染數(shù)據(jù)的示例代碼
今天小編就為大家分享一篇使用Vue調(diào)取接口,并渲染數(shù)據(jù)的示例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
Vue.js使用axios動態(tài)獲取response里的data數(shù)據(jù)操作
這篇文章主要介紹了Vue.js使用axios動態(tài)獲取response里的data數(shù)據(jù)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
使用axios發(fā)送post請求,將JSON數(shù)據(jù)改為form類型的示例
今天小編就為大家分享一篇使用axios發(fā)送post請求,將JSON數(shù)據(jù)改為form類型的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
vue post application/x-www-form-urlencoded如何實現(xiàn)傳參
這篇文章主要介紹了vue post application/x-www-form-urlencoded如何實現(xiàn)傳參問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
vuex state及mapState的基礎(chǔ)用法詳解
這篇文章主要介紹了vuex state及mapState的基礎(chǔ)用法詳解,本文通過實例代碼相結(jié)合的形式給大家介紹的非常詳細,需要的朋友跟隨腳本之家小編一起學(xué)習吧2018-04-04

