Was ist Keep-Alive? Der folgende Artikel wird über Ihr Verständnis der in vue integrierten Komponente Keep-Alive sprechen. Ich hoffe, er wird Ihnen hilfreich sein!
keep-alive
ist eine integrierte Komponente in vue
, die den Zustand während des Komponentenwechsels beibehalten kann . Verhindern Sie im Speicher das wiederholte Rendern von DOM
. [Verwandte Empfehlungen: vuejs-Video-Tutorialkeep-alive
是vue
中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM
。【相关推荐:vuejs视频教程、web前端开发】
keep-alive
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
keep-alive
可以设置以下props
属性:
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存max
- 数字。最多可以缓存多少组件实例关于keep-alive
的基本用法:
<keep-alive> <component :is="view"></component> </keep-alive>
使用includes
和exclude
:
<keep-alive include="a,b"> <component :is="view"></component> </keep-alive> <!-- 正则表达式 (使用 `v-bind`) --> <keep-alive :include="/a|b/"> <component :is="view"></component> </keep-alive> <!-- 数组 (使用 `v-bind`) --> <keep-alive :include="['a', 'b']"> <component :is="view"></component> </keep-alive>
匹配首先检查组件自身的 name
选项,如果 name
选项不可用,则匹配它的局部注册名称 (父组件 components
选项的键值),匿名组件不能被匹配
设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activated
与deactivated
):
beforeRouteEnter
> beforeCreate
> created
> mounted
> activated
> ... ... > beforeRouteLeave
> deactivated
beforeRouteEnter
>activated
> ... ... > beforeRouteLeave
> deactivated
使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive
举个栗子:
当我们从首页
–>列表页
–>商详页
–>再返回
,这时候列表页应该是需要keep-alive
从首页
–>列表页
–>商详页
–>返回到列表页(需要缓存)
–>返回到首页(需要缓存)
–>再次进入列表页(不需要缓存)
,这时候可以按需来控制页面的keep-alive
在路由中设置keepAlive
属性判断是否需要缓存
{ path: 'list', name: 'itemList', // 列表页 component (resolve) { require(['@/pages/item/list'], resolve) }, meta: { keepAlive: true, title: '列表页' } }
使用<keep-alive>
<div id="app" class='wrapper'> <keep-alive> <!-- 需要缓存的视图组件 --> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <!-- 不需要缓存的视图组件 --> <router-view v-if="!$route.meta.keepAlive"></router-view> </div>
keep-alive
是vue
中内置的一个组件
源码位置:src/core/components/keep-alive.js
export default { name: 'keep-alive', abstract: true, props: { include: [String, RegExp, Array], exclude: [String, RegExp, Array], 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 = getFirstComponentChild(slot) /* 获取该组件节点的componentOptions */ const componentOptions = vnode && vnode.componentOptions if (componentOptions) { /* 获取该组件节点的名称,优先获取组件的name字段,如果name不存在则获取组件的tag */ const name = getComponentName(componentOptions) const { include, exclude } = this /* 如果name不在inlcude中或者存在于exlude中则表示不缓存,直接返回vnode */ if ( (include && (!name || !matches(include, name))) || // excluded (exclude && name && matches(exclude, name)) ) { return vnode } const { cache, keys } = this /* 获取组件的key值 */ 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 /* 拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存 */ 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 /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */ if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } } vnode.data.keepAlive = true } return vnode || (slot && slot[0]) } }
可以看到该组件没有template
,而是用了render
,在组件渲染的时候会自动执行render
函数
this.cache
是一个对象,用来存储需要缓存的组件,它将以如下形式存储:
this.cache = { 'key1':'组件1', 'key2':'组件2', // ... }
在组件销毁的时候执行pruneCacheEntry
函数
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) }
在mounted
钩子函数中观测 include
和 exclude
的变化,如下:
mounted () { this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }
如果include
或exclude
发生了变化,即表示定义需要缓存的组件的规则或者不需要缓存的组件的规则发生了变化,那么就执行pruneCache
函数,函数如下:
function pruneCache (keepAliveInstance, filter) { const { cache, keys, _vnode } = keepAliveInstance for (const key in cache) { const cachedNode = cache[key] if (cachedNode) { const name = getComponentName(cachedNode.componentOptions) if (name && !filter(name)) { pruneCacheEntry(cache, key, keys, _vnode) } } } }
在该函数内对this.cache
对象进行遍历,取出每一项的name
值,用其与新的缓存规则进行匹配,如果匹配不上,则表示在新的缓存规则下该组件已经不需要被缓存,则调用pruneCacheEntry
函数将其从this.cache
对象剔除即可
关于keep-alive
的最强大缓存功能是在render
函数中实现
首先获取组件的key
值:
const key = vnode.key == null? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '') : vnode.key
拿到key
值后去this.cache
, Web-Frontend-Entwicklung
keep-alive
Beim Umschließen dynamischer Komponenten der Cache werden inaktive Komponenteninstanzen sein, anstatt sie zu zerstören. 🎜🎜keep-alive
kann die folgenden props
-Eigenschaften festlegen: 🎜include
– Zeichenfolge oder regulärer Ausdruck. Nur Komponenten mit übereinstimmenden Namen werden zwischengespeichertexclude
– String oder regulärer Ausdruck. Jede Komponente mit einem übereinstimmenden Namen wird nicht zwischengespeichertmax
– Zahl. Die maximale Anzahl von Komponenteninstanzen, die zwischengespeichert werden könnenkeep-alive
: 🎜/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */ if (cache[key]) { vnode.componentInstance = cache[key].componentInstance /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */ remove(keys, key) keys.push(key) }
includes
und exclude </code >: 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">/* 如果没有命中缓存,则将其设置进缓存 */
else {
cache[key] = vnode
keys.push(key)
/* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div><div class="contentsignin">Nach dem Login kopieren</div></div>🎜Der Abgleich prüft zunächst die Option <code>name
der Komponente selbst. Wenn die Option name
nicht verfügbar ist, wird deren lokaler Registrierungsname (übergeordnetes Element) abgeglichen Komponente components</ code> Optionsschlüsselwert), anonyme Komponenten können nicht abgeglichen werden 🎜🎜Komponenten mit eingerichtetem Keep-Alive-Cache verfügen über zwei weitere Lebenszyklus-Hooks (<code>aktiviert
und deaktiviert).
): 🎜beforeRouteEnter
> beforeCreate
> > aktiviert
> beforeRouteLeave
> li>beforeRouteEnter
>aktiviert
> code>deaktiviert li>keepalive
verwenden >Geschäftsdetailseite–> ;Zurück
Zu diesem Zeitpunkt sollte die Listenseite am Leben bleiben
🎜🎜von der Startseite</code sein >–><code>Listenseite</code >–><code>Geschäftsdetailseite
–>Zurück zur Listenseite (Caching erforderlich)
–> Zurück zur Startseite (Caching erforderlich)
– >Geben Sie die Listenseite erneut ein (kein Caching erforderlich)
. Zu diesem Zeitpunkt können Sie das Keep-Alive
steuern der Seite nach Bedarf🎜🎜Das Attribut keepAlive im Routing-Code> festlegen legt fest, ob Caching erforderlich ist🎜beforeRouteEnter(to, from, next){
next(vm=>{
console.log(vm)
// 每次进入路由执行
vm.getData() // 获取数据
})
},
Nach dem Login kopierenNach dem Login kopieren🎜Verwenden Sie <keep-alive>
🎜activated(){
this.getData() // 获取数据
},
Nach dem Login kopierenNach dem Login kopieren🎜3. Prinzipanalyse🎜🎜🎜keep -alive
ist eine in vue
integrierte Komponente. 🎜🎜Quellcode-Speicherort: src/core/components/keep -alive.js🎜rrreee🎜Sie können sehen, dass diese Komponente kein template
hat, sondern render
verwendet, wodurch das render
automatisch ausgeführt wird Funktion beim Rendern der Komponente🎜🎜this.cache
ist ein Objekt, das zum Speichern von Komponenten verwendet wird, die zwischengespeichert werden müssen. Es wird in der folgenden Form gespeichert: 🎜rrreee🎜Führen Sie den pruneCacheEntry aus
-Funktion, wenn die Komponente zerstört wird 🎜rrreee🎜Beobachten Sie die Hook-Funktion mount
< Die Änderungen in Code>include
und exclude
sind wie folgt: 🎜rrreee🎜Wenn sich include
oder exclude
ändert, bedeutet dies, dass die Definition erforderlich ist. Wenn sich die Regeln von zwischengespeicherten Komponenten oder die Regeln von Komponenten, die nicht zwischengespeichert werden müssen, geändert haben, Führen Sie dann die Funktion pruneCache
aus. Die Funktion lautet wie folgt: 🎜rrreee🎜Aktualisieren Sie in dieser Funktion this.cache</code >Traversieren Sie das Objekt und nehmen Sie den <code>Name</ heraus. Geben Sie den Wert jedes Elements ein und verwenden Sie ihn, um ihn mit der neuen Caching-Regel abzugleichen. Wenn er nicht übereinstimmt, bedeutet dies, dass die Komponente nicht mehr unter der neuen Caching-Regel zwischengespeichert werden muss. Rufen Sie dann den <code>pruneCacheEntry</ auf. code>-Funktion, um es aus dem <code>this.cache
-Objekt zu entfernen🎜🎜Die leistungsstärkste Caching-Funktion von keep-alive
ist im render
implementiert Funktion 🎜🎜Erhalten Sie zuerst den key
-Wert der Komponente: 🎜rrreee🎜Nachdem Sie den key
-Wert erhalten haben, gehen Sie zum this.cache
-Objekt, um es zu finden Wenn dieser Wert vorhanden ist, bedeutet dies, dass die Komponente einen Cache hat, d. h. sie trifft auf den Cache wie folgt: 🎜/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */ if (cache[key]) { vnode.componentInstance = cache[key].componentInstance /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */ remove(keys, key) keys.push(key) }
直接从缓存中拿 vnode
的组件实例,此时重新调整该组件key
的顺序,将其从原来的地方删掉并重新放在this.keys
中最后一个
this.cache
对象中没有该key
值的情况,如下:
/* 如果没有命中缓存,则将其设置进缓存 */ else { cache[key] = vnode keys.push(key) /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */ if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } }
表明该组件还没有被缓存过,则以该组件的key
为键,组件vnode
为值,将其存入this.cache
中,并且把key
存入this.keys
中
此时再判断this.keys
中缓存组件的数量是否超过了设置的最大缓存数量值this.max
,如果超过了,则把第一个缓存组件删掉
解决方案可以有以下两种:
每次组件渲染的时候,都会执行beforeRouteEnter
beforeRouteEnter(to, from, next){ next(vm=>{ console.log(vm) // 每次进入路由执行 vm.getData() // 获取数据 }) },
在keep-alive
缓存的组件被激活的时候,都会执行actived
钩子
activated(){ this.getData() // 获取数据 },
注意:服务器端渲染期间avtived
不被调用
Das obige ist der detaillierte Inhalt vonLassen Sie uns über das Verständnis der integrierten Keep-Alive-Komponente von Vue sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!