likes
comments
collection
share

Vue之keep-alive从基础到实战 (vue2\vue3)

作者站长头像
站长
· 阅读数 34

直接进入主题

一般使用的到的场景

  1. 从 详情页 --> 列表页 的时候页面的状态是缓存,不用重新请求数据,提升用户体验
  2. 有一个可以进行筛选的列表页List.vue,点击某一项时进入相应的详情页面,等到你从详情页返回List.vue时,发现列表页居然刷新了!刚刚的筛选条件都没了!!!
  3. 页面中有大量的canvas、svg等等比较耗费性能的渲染时 例如:”浙江碳普惠“中首页用到了konva、lottie,首页多次切换会产生大量内存占用,于是对首页进行了缓存,但是有个问题是有些数据还是要及时更新,所以用到了onActivated这个钩子,在里面进行相关逻辑的处理。

Vue之keep-alive从基础到实战 (vue2\vue3)

keep-alive是什么

  • keep-alive是一个Vue全局组件
  • keep-alive本身不会渲染出来,也不会出现在父组件链中
  • keep-alive包裹动态组件时,会缓存不活动的组件,而不是销毁它们

keep-alive怎么用

keep-alive接收三个参数:

  • include:可传字符串、正则表达式、数组,名称匹配成功的组件会被缓存
  • exclude:可传字符串、正则表达式、数组,名称匹配成功的组件不会被缓存
  • max:可传数字,限制缓存组件的最大数量

includeexclude,传数组情况居多

先看下官网使用示例

<!-- 基本 --> 
<keep-alive> 
    <component :is="view"></component>
</keep-alive>

<!-- 多个条件判断的子组件 -->
<keep-alive>
    <comp-a v-if="a > 1"></comp-a>
    <comp-b v-else></comp-b> 
</keep-alive>

<!-- 和 `<transition>` 一起使用 -->
<transition> 
    <keep-alive>
        <component :is="view"></component> 
    </keep-alive>
</transition>

<!-- 逗号分隔字符串 只缓存组件name为a或者b的组件 -->
<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>

<keep-alive :max="10">
    <component :is="view"></component> 
</keep-alive>

keep-alive包含的组件不会被再次初始化,也就意味着不会重走生命周期函数 但是有时候是希望我们缓存的组件可以能够再次进行渲染,这时Vue为我们解决了这个问题 被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activateddeactivated

  • activatedkeep-alive 包含的组件再次渲染的时候触发
  • deactivatedkeep-alive 包含的组件销毁的时候触发
// vue3 示例
import { onActivated } from "vue";

onActivated(() => {
  // do something ...
});

配合router使用

// router配置
   {
      path: "/home",
      component: () => import("../views/home/index.vue"),
      meta: {
        title: "首页",
        keepAlive: true
      }
    }
    
// App.vue

// vue2 示例
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>

// vue3 示例
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component
        :is="Component"
        :key="$route.name"
        v-if="$route.meta.keepAlive"
      />
    </keep-alive>
    <component
      :is="Component"
      :key="$route.name"
      v-if="!$route.meta.keepAlive"
    />
  </router-view>

动态设置keepAlive属性

// 使用组件内守卫,对离开页面事件做一些操作
// to为即将跳转的路由,from为上一个页面路由
beforeRouteEnter(to, from, next) {
  to.meta.keepAlive = true;
  // 路由继续跳转
  next();
}

删除keep-alive的方法

beforeRouteLeave:function(to, from, next){ 
    if(to.name=='Login'){
        if (this.$vnode && this.$vnode.data.keepAlive){
            if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache){
                if (this.$vnode.componentOptions){
                    var key = this.$vnode.key == null? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : ''): this.$vnode.key;
                    var cache = this.$vnode.parent.componentInstance.cache;
                    var keys = this.$vnode.parent.componentInstance.keys;
                    if (cache[key]){
                        if (keys.length) {
                            var index = keys.indexOf(key);
                            if (index > -1) {
                                keys.splice(index, 1);
                            }
                         } 
                         delete cache[key];
                     }
                 }
             }
         }
     } 
     // this.$destroy();
     next();
},

踩坑点

  1. vue多级菜单(路由)导致缓存(keep-alive)失效(在二级路由中配置同样的router-view解决)
转载自:https://juejin.cn/post/7094910768285483039
评论
请登录