Created
September 11, 2023 02:14
-
-
Save LittleSaya/2a09c3ec5d450138cd507ead1c8259eb to your computer and use it in GitHub Desktop.
keep-alive-2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
const eventBus = new Vue(); | |
export default eventBus; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { getComponentName, getFirstComponentChild, isArray, isRegExp, remove } from './util' | |
import keepAlive2Events from './events' | |
function _getComponentName(opts) { | |
return opts && (getComponentName(opts.Ctor.options) || opts.tag) | |
} | |
function matches( | |
pattern, | |
name | |
) { | |
if (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 | |
} | |
function pruneCache( | |
keepAliveInstance, | |
filter | |
) { | |
const { cache, keys, _vnode } = keepAliveInstance | |
for (const key in cache) { | |
const entry = cache[key] | |
if (entry) { | |
const name = entry.name | |
if (name && !filter(name)) { | |
pruneCacheEntry(cache, key, keys, _vnode) | |
} | |
} | |
} | |
} | |
function pruneCacheEntry( | |
cache, | |
key, | |
keys, | |
current | |
) { | |
const entry = cache[key] | |
if (entry && (!current || entry.tag !== current.tag)) { | |
entry.componentInstance.$destroy() | |
} | |
cache[key] = null | |
remove(keys, key) | |
} | |
const patternTypes = [String, RegExp, Array] | |
export default { | |
name: 'keep-alive-2', | |
abstract: true, | |
props: { | |
include: patternTypes, | |
exclude: patternTypes, | |
max: [String, Number] | |
}, | |
methods: { | |
cacheVNode() { | |
const { cache, keys, vnodeToCache, keyToCache } = this | |
// console.log('dbg keep-alive-2 cacheVNode keyToCache', keyToCache) | |
if (vnodeToCache) { | |
const { tag, componentInstance, componentOptions } = vnodeToCache | |
cache[keyToCache] = { | |
name: _getComponentName(componentOptions), | |
tag, | |
componentInstance | |
} | |
keys.push(keyToCache) | |
// prune oldest entry | |
if (this.max && keys.length > parseInt(this.max)) { | |
pruneCacheEntry(cache, keys[0], keys, this._vnode) | |
} | |
this.vnodeToCache = null | |
} | |
}, | |
onRemove(vnode) { | |
const componentOptions = vnode && vnode.componentOptions | |
const keyToRemove = | |
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; | |
const { cache, keys } = this | |
pruneCacheEntry(cache, keyToRemove, keys, this._vnode) | |
} | |
}, | |
created() { | |
this.cache = Object.create(null) | |
this.keys = [] | |
keepAlive2Events.$on('remove', this.onRemove); | |
}, | |
destroyed() { | |
for (const key in this.cache) { | |
pruneCacheEntry(this.cache, key, this.keys) | |
} | |
keepAlive2Events.$off('remove', this.onRemove); | |
}, | |
mounted() { | |
this.cacheVNode() | |
this.$watch('include', val => { | |
pruneCache(this, name => matches(val, name)) | |
}) | |
this.$watch('exclude', val => { | |
pruneCache(this, name => !matches(val, name)) | |
}) | |
}, | |
updated() { | |
this.cacheVNode() | |
}, | |
render() { | |
const slot = this.$slots.default | |
const vnode = getFirstComponentChild(slot) | |
const componentOptions = vnode && vnode.componentOptions | |
if (componentOptions) { | |
// check pattern | |
const name = _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 = | |
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 { | |
// delay setting the cache until update | |
this.vnodeToCache = vnode | |
this.keyToCache = key | |
} | |
// @ts-expect-error can vnode.data can be undefined | |
vnode.data.keepAlive = true | |
} | |
return vnode || (slot && slot[0]) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const isArray = Array.isArray | |
export function isDef(v) { | |
return v !== undefined && v !== null | |
} | |
export function isRegExp(v) { | |
return _toString.call(v) === '[object RegExp]' | |
} | |
export function isAsyncPlaceholder(node) { | |
return node.isComment && node.asyncFactory | |
} | |
export function remove(arr, item) { | |
const len = arr.length | |
if (len) { | |
// fast path for the only / last item | |
if (item === arr[len - 1]) { | |
arr.length = len - 1 | |
return | |
} | |
const index = arr.indexOf(item) | |
if (index > -1) { | |
return arr.splice(index, 1) | |
} | |
} | |
} | |
export function getComponentName(options) { | |
return options.name || options.__name || options._componentTag | |
} | |
export function getFirstComponentChild(children) { | |
if (isArray(children)) { | |
for (let i = 0; i < children.length; i++) { | |
const c = children[i] | |
if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) { | |
return c | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment