Home > Web Front-end > Vue.js > Let's talk about our understanding of Vue's built-in component keep-alive

Let's talk about our understanding of Vue's built-in component keep-alive

青灯夜游
Release: 2022-12-14 20:15:39
forward
1966 people have browsed it

What is Keep-alive? The following article will talk about your understanding of the vue

Let's talk about our understanding of Vue's built-in component keep-alive

1. What is Keep-alive

keep-alivevue## The built-in components in # can retain the state in memory during component switching to prevent repeated rendering DOM. [Related recommendations: vuejs video tutorial, web front-end development]

keep-alive

keep-aliveYou can set the following props

  • include
  • exclude
  • max
About the basic usage of

keep-alive:

<keep-alive>
  <component :is="view"></component>
</keep-alive>
Copy after login

Use

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>
Copy after login
namename

Components with keep-alive cache set up will have two more life cycle hooks (

activated):

    When entering the component for the first time:
  • beforeRouteEnterbeforeCreatecreated> activatedbeforeRouteLeavedeactivated
  • When entering the component again:
  • beforeRouteEnteractivatedbeforeRouteLeavedeactivated

2. Usage scenarios

Principle of use: When we do not need to reload the page in certain scenarios, we can use

keepalive

When we go from

Homepage–>List page–>Business details page–>. At this time, the list page should need to keep-alive

from the

homepage–>list page–>Business details page–>Return to the list page (requires caching)–>Return to homepage (requires caching)–>Enter the list again page (no need to cache), at this time you can control the keep-alivekeepAlive

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

Use

<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>
Copy after login

3. Principle Analysis

keep-alivevue

Source code location: 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])
  }
}
Copy after login

You can see that the component does not have

templaterender, which will automatically execute the render

this.cache

this.cache = {
    &#39;key1&#39;:&#39;组件1&#39;,
    &#39;key2&#39;:&#39;组件2&#39;,
    // ...
}
Copy after login

Executed when the component is destroyed

pruneCacheEntryfunction

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)
}
Copy after login

ininclude
exclude
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))
    })
}
Copy after login

If

includeexcludepruneCache

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)
      }
    }
  }
}
Copy after login
this.cachenamepruneCacheEntrythis.cache

About

keep-alive The most powerful caching function of renderkey

const key = vnode.key == null? 
componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : &#39;&#39;)
: vnode.key
Copy after login

get# After the ##keythis.cache
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */ if (cache[key]) { vnode.componentInstance = cache[key].componentInstance /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */ remove(keys, key) keys.push(key) }</pre><div class="contentsignin">Copy after login</div></div><p>直接从缓存中拿 <code>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)
    }
}
Copy after login

表明该组件还没有被缓存过,则以该组件的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()  // 获取数据
    })
},
Copy after login

actived

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

activated(){
   this.getData() // 获取数据
},
Copy after login

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

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

The above is the detailed content of Let's talk about our understanding of Vue's built-in component keep-alive. For more information, please follow other related articles on the PHP Chinese website!

source:juejin.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template