Heim > Web-Frontend > View.js > Hauptteil

Lassen Sie uns über das Verständnis der integrierten Keep-Alive-Komponente von Vue sprechen

青灯夜游
Freigeben: 2022-12-14 20:15:39
nach vorne
1925 Leute haben es durchsucht

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!

Lassen Sie uns über das Verständnis der integrierten Keep-Alive-Komponente von Vue sprechen

1. Was ist Keep-alive

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-alivevue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM 。【相关推荐:vuejs视频教程web前端开发

keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

keep-alive可以设置以下props属性:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存
  • max - 数字。最多可以缓存多少组件实例

关于keep-alive的基本用法:

<keep-alive>
  <component :is="view"></component>
</keep-alive>
Nach dem Login kopieren

使用includesexclude

<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="[&#39;a&#39;, &#39;b&#39;]">
  <component :is="view"></component>
</keep-alive>
Nach dem Login kopieren

匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值),匿名组件不能被匹配

设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activateddeactivated):

  • 首次进入组件时:beforeRouteEnter > beforeCreate > created> mounted > activated > ... ... > beforeRouteLeave > deactivated
  • 再次进入组件时:beforeRouteEnter >activated > ... ... > beforeRouteLeave > deactivated

二、使用场景

使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive

举个栗子:

当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive

首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存),这时候可以按需来控制页面的keep-alive

在路由中设置keepAlive属性判断是否需要缓存

{
  path: &#39;list&#39;,
  name: &#39;itemList&#39;, // 列表页
  component (resolve) {
    require([&#39;@/pages/item/list&#39;], resolve)
 },
 meta: {
  keepAlive: true,
  title: &#39;列表页&#39;
 }
}
Nach dem Login kopieren

使用<keep-alive>

<div id="app" class=&#39;wrapper&#39;>
    <keep-alive>
        <!-- 需要缓存的视图组件 --> 
        <router-view v-if="$route.meta.keepAlive"></router-view>
     </keep-alive>
      <!-- 不需要缓存的视图组件 -->
     <router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
Nach dem Login kopieren

三、原理分析

keep-alivevue中内置的一个组件

源码位置:src/core/components/keep-alive.js

export default {
  name: &#39;keep-alive&#39;,
  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(&#39;include&#39;, val => {
      pruneCache(this, name => matches(val, name))
    })
    this.$watch(&#39;exclude&#39;, 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}` : &#39;&#39;)
        : 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])
  }
}
Nach dem Login kopieren

可以看到该组件没有template,而是用了render,在组件渲染的时候会自动执行render函数

this.cache是一个对象,用来存储需要缓存的组件,它将以如下形式存储:

this.cache = {
    &#39;key1&#39;:&#39;组件1&#39;,
    &#39;key2&#39;:&#39;组件2&#39;,
    // ...
}
Nach dem Login kopieren

在组件销毁的时候执行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)
}
Nach dem Login kopieren

mounted钩子函数中观测 includeexclude 的变化,如下:

mounted () {
    this.$watch(&#39;include&#39;, val => {
        pruneCache(this, name => matches(val, name))
    })
    this.$watch(&#39;exclude&#39;, val => {
        pruneCache(this, name => !matches(val, name))
    })
}
Nach dem Login kopieren

如果includeexclude 发生了变化,即表示定义需要缓存的组件的规则或者不需要缓存的组件的规则发生了变化,那么就执行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)
      }
    }
  }
}
Nach dem Login kopieren

在该函数内对this.cache对象进行遍历,取出每一项的name值,用其与新的缓存规则进行匹配,如果匹配不上,则表示在新的缓存规则下该组件已经不需要被缓存,则调用pruneCacheEntry函数将其从this.cache对象剔除即可

关于keep-alive的最强大缓存功能是在render函数中实现

首先获取组件的key值:

const key = vnode.key == null? 
componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : &#39;&#39;)
: vnode.key
Nach dem Login kopieren

拿到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 zwischengespeichert
  • exclude – String oder regulärer Ausdruck. Jede Komponente mit einem übereinstimmenden Namen wird nicht zwischengespeichert
  • max – Zahl. Die maximale Anzahl von Komponenteninstanzen, die zwischengespeichert werden können
🎜Grundlegende Verwendung von keep-alive: 🎜
/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */
if (cache[key]) {
    vnode.componentInstance = cache[key].componentInstance
    /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */
    remove(keys, key)
    keys.push(key)
}
Nach dem Login kopieren
Nach dem Login kopieren
🎜Verwenden Sie 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 &amp;&amp; keys.length &gt; 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). ): 🎜
  • Beim ersten Betreten der Komponente: beforeRouteEnter > beforeCreate > > aktiviert > beforeRouteLeave > li>
  • Geben Sie die Komponente erneut ein. Wenn: beforeRouteEnter >aktiviert > code>deaktiviert

🎜2. Nutzungsszenarien🎜🎜🎜Nutzungsprinzip: Wenn wir die Seite nicht neu laden müssen In einigen Szenarien können wir 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 festlegen legt fest, ob Caching erforderlich ist🎜
beforeRouteEnter(to, from, next){
    next(vm=>{
        console.log(vm)
        // 每次进入路由执行
        vm.getData()  // 获取数据
    })
},
Nach dem Login kopieren
Nach dem Login kopieren
🎜Verwenden Sie <keep-alive>🎜
activated(){
   this.getData() // 获取数据
},
Nach dem Login kopieren
Nach 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)
}
Nach dem Login kopieren
Nach dem Login kopieren

直接从缓存中拿 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)
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

表明该组件还没有被缓存过,则以该组件的key为键,组件vnode为值,将其存入this.cache中,并且把key存入this.keys

此时再判断this.keys中缓存组件的数量是否超过了设置的最大缓存数量值this.max,如果超过了,则把第一个缓存组件删掉

四、思考题:缓存后如何获取数据

解决方案可以有以下两种:

  • beforeRouteEnter
  • actived

beforeRouteEnter

每次组件渲染的时候,都会执行beforeRouteEnter

beforeRouteEnter(to, from, next){
    next(vm=>{
        console.log(vm)
        // 每次进入路由执行
        vm.getData()  // 获取数据
    })
},
Nach dem Login kopieren
Nach dem Login kopieren

actived

keep-alive缓存的组件被激活的时候,都会执行actived钩子

activated(){
   this.getData() // 获取数据
},
Nach dem Login kopieren
Nach dem Login kopieren

注意:服务器端渲染期间avtived不被调用

(学习视频分享:vuejs入门教程编程基础视频

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!

Verwandte Etiketten:
Quelle:juejin.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage