vue中tab标签页keep-alive二级路由+删除指定缓存页面

1.实现效果

keep-alive.gif

2.keep-alive

2.1是什么:

keep-alive 是 Vue 的内置组件,keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 transition 相似,keep-alive是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。

2.2做什么:

在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。主要用于保留组件状态或避免重新渲染。比如:列表进详情页面,面包屑跳转页面等。

2.3怎么用:

1.基本用法

<!-- 基本 -->
<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>

2.当组件在 keep-alive 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

  • activated:在 keep-alive 组件激活时调用,服务器端渲染期间不被调用。在被缓存页面可以替代created更新数据。
  • deactivated:在 keep-alive 组件停用时调用,服务器端渲染期间不被调用。

3.Props:

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

include 和 exclude prop 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:

<!-- 逗号分隔字符串 -->
<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 选项的键值)。匿名组件不能被匹配。

4.项目中的一些用法

  • 路由元信息中的keepAlive判断是否缓存
<!-- 结合路由一起使用 -->
<keep-alive>
  <router-view v-if="$route.meta.keepAlive"></router-view>
 </keep-alive>
 <router-view v-if="!$route.meta.keepAlive"></router-view>
  • 路由钩子中动态设置keepAlive
beforeRouteLeave (to, from, next) {
  if (to.path === 'xxx') {
    from.meta.keepAlive = true
  } else {
    from.meta.keepAlive = false
  }
  next()
},
  • vuex+include动态缓存组件

3.实现步骤

方法一.vuex+include

为每个页面设置不重复的name字段,当点击菜单栏的时候,将点击的组件的name值存入catch_components中,当点击关闭标签时,删除该项。

<keep-alive :include="catch_components" :max="10">
 <router-view></router-view>
</keep-alive>
index.vue:
computed:{
 ...mapState({
    catch_components: (state) => state.catch_components, // keepalive缓存
  }),
}
//点击选中某菜单
selectMenu(item, i, subName) {
   // 方法一:利用include
   this.$store.commit("addKeepAliveCache", item.name);
   var submenu = {
     path: item.path,
     name: item.name,
     label: item.title,
     index: i,
     subName: subName,
   };
   this.$store.commit("selectMenu", submenu);
   this.$router.push({ path: item.path });
 },
 
//关闭某个菜单
  handleClose(tab, index) {
    // 删除keepAlive缓存
    // 方法一:利用include
    this.$store.commit("removeKeepAliveCache", tab.name);
  },
vuex:
// 添加keepalive缓存
addKeepAliveCache(state, val) {
     if (val === '/homepage') {
         return;
     }
     if (state.catch_components.indexOf(val) === -1) {
         state.catch_components.push(val);
     }
 },
 // 删除keepalive缓存
removeKeepAliveCache(state, val) {
    let cache = state.catch_components;
    for (let i = 0; i < cache.length; i++) {
        if (cache[i] === val) {
            cache.splice(i, 1);
        }
    }
    state.catch_components = cache;
},

方法2.vuex+暴力删除cache和keys

无需设置页面的name字段,当点击菜单栏的时候,将点击的组件的路径值存入catch_components中,当关闭按钮时候,删除该路径,并找到当前已缓存的cache和keys,暴力删除该缓存页面。

<keep-alive :max="10">
 <router-view
    :key="$route.path"
    v-if="catch_components.includes(this.$route.path)"
  ></router-view>
</keep-alive>
<router-view
  :key="$route.path"
  v-if="!catch_components.includes(this.$route.path)"
></router-view>

如何拿到当前已缓存的cache和keys

  • 路由钩子函数中获取(此方法只能是关闭当前路由页面才能获取到)
beforeRouteLeave(to, from, next) {
  let cache = this.$vnode.parent.componentInstance.cache; //缓存的组件路径
   let keys = this.$vnode.parent.componentInstance.keys; // 缓存的组件key值
   next()
 },
  • computed中获取(这个方法可以监听到当前页面离开或点击关闭按钮离开)
cache: {
   get() {
     if (!this.$route.matched[1]) return;
     const instances = this.$route.matched[1].instances;
     return instances && instances.default && instances.default.$vnode
       ? instances.default.$vnode.parent.componentInstance.cache
       : {};
   },
   set(val) {
     this.$route.matched[1].instances.default.$vnode.parent.componentInstance.cache =
       val;
   },
 },
 cache_key: {
   get() {
     if (!this.$route.matched[1]) return;
     const instances = this.$route.matched[1].instances;
     return instances && instances.default && instances.default.$vnode
       ? instances.default.$vnode.parent.componentInstance.keys
       : [];
   },
   set(val) {
     this.$route.matched[1].instances.default.$vnode.parent.componentInstance.keys =
       val;
   },
 },
   
index.vue
//当关闭tab标签时候,删除指定缓存
 handleClose(tab, index) {
    // console.log("缓存-------------------------------", this.cache);
    // console.log("keys---------------------------------", this.cache_key);
    let cache = this.cache,
        keys = this.cache_key;
    if (cache[tab.path] != null) {
        delete cache[tab.path];
        keys.splice(keys.indexOf(tab.path), 1);
    }
    // 删除keepAlive缓存
    // 方法二:利用path
    this.$store.commit("removeKeepAliveCache", tab.path);
 },

4.完整代码,更新在苏苏的码云如果对你有帮助,欢迎你的star+订阅!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360

推荐阅读更多精彩内容