keep-alive(vue)

72 阅读2分钟

keep-alive简介

keep-alive是vue的一个组件,用来缓存其它组件,保留状态,避免重新渲染。用法比较简单,将组件作为keep-alive插槽就可以了。

<keep-alive>  
    <component>    
    <!-- 该组件将被缓存! -->  
    </component>
</keep-alive>

对于缓存的组件,多了activated(激活)和deactivated(失活)两个钩子。组件第二次进入不会走created和mounted钩子了,只会走activated

属性props

有三个属性

  • include - 可传字符串、正则表达式、数组。只有名称匹配的组件会被缓存。
  • exclude - 可传字符串、正则表达式、数组。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。
<keep-alive :include="a" :max="2"> 
    <router-view></router-view> 
</keep-alive>

常与路由配合使用

router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存。可利用include/exclude针对性缓存组件

  {
      path: "/home",
      name: 'home',   
      component: () => import(/* webpackChunkName: "home" */ '@/pages/home'),
      meta: {
        title: '首页', 
        keepAlive: true
      },
    },
<keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive && isRouterAlive"></router-view>

B->A要缓存,C-A要刷新,怎么办? 利用beforeRouteLeave钩子修改meta.keepAlive的属性。B组件里设置为true,C里设置false

// B
beforeRouteLeave(to, from, next) {             

    // 设置下一个路由的 meta            

    to.meta.keepAlive = true;  

    next();        

}};

原理

主要看看源码的缓存机制

      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并且缓存的长度超了,从缓存中删除第一个
        if (this.max && keys.length > parseInt(this.max)) {
          pruneCacheEntry(cache, keys[0], keys, this._vnode)
        }
      }

      vnode.data.keepAlive = true

如果命中缓存,则直接从缓存中拿 vnode 的组件实例,采用LRU(Least recently used,最近最少使用)算法;如果没有命中将其放在缓存里面。 LRU算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

  • 将新数据从尾部插入到this.keys中;
  • 每当缓存命中(即缓存数据被访问),则将数据移到this.keys的尾部;
  • this.keys满的时候,将头部的数据丢弃;