vue组件中如何动态管理keep-alive缓存的组件?

问题描述

问题的发生总是源于需求。所以我先描述下我的业务场景:
左右布局的页面,左侧是一列Tabs 标签页,右侧是一棵树,点击tab的每一项,右侧树的勾选状态发生变化。左侧的tab项可以动态的增加删除。特殊说明一下,右侧的树,是同一棵树,只是勾选状态不一样。
图片描述

问题出现的环境背景及自己尝试过哪些方法

看到这个需求后,其实这就是典型的Tabs 标签页。点击tab标签,内容区进行切换。左侧一个tab对应右侧一棵树。
所以我这里会有2个list,一个TabList(左侧),一个TreeList(右侧).

开发思路
左侧TabList添加一个tab,右侧TreeList添加一棵树,tab切换时,右侧树v-show去隐藏显示,但是这样的问题就是dom节点在tab不断增加的情况下也不断增加,树本来就dom节点多,所以v-show的方案就直接放弃了。那么v-if去切换,这样就可以解决了dom节点数多的问题。但是也会引入另外一个问题,就是如何保持树的状态,例如一个数,有自己的勾选状态、展开状态、滚动条的状态,虽然使用了element ui的树,可以解决勾选状态、展开状态,但是滚动状态就需要自己去维护,说不定以后还有其他状态,干脆一不做二不休,为什么不使用keep-alive方案呢?既可以解决dom节点多的问题,又可以保持状态,简直完美。就用keep-alive方案。

相关代码

这是目前的实现方案:代码是简化过的代码,为了更好的说明,删除了其他业务逻辑。

<template>
  <div class="hello">

    <button @click="onAdd">+</button>
    <span class='num'
      :class='{active:item.id==activeTab}'
      @click='onShowTree(item)'
      v-for="(item,index) in TabList"
      v-if='!item.isDel'
      :key="index">
      {{item.id}}
      <button @click.stop="onDel(item)">-</button>
    </span>

    <keep-alive>
      <tree v-for="(item,index) in TabList"
        v-if="item.id==activeTab"
        :key='index'></tree>
    </keep-alive>
  </div>
</template>

<script>
import axios from "axios";
import _ from "lodash";
import tree from "./tree";
let components = {};
export default {
  name: "parent-component",
  components: {
    tree
  },
  data() {
    return {
      activeTab: "",
      TabList: []
    };
  },
  computed: {

  },
  methods: {
    onShowTree(item) {
      this.activeTab = item.id;
    },
    onAdd() {
      let id = this.TabList.length;
      let isDel = false;
      this.TabList.push({ id,isDel });
    },
    onDel(item) {
      item.isDel = true;
    }
  }
};
</script>
这个方案,目前是解决了我的问题,但是却存在2个问题。
1.我需要多加一个字段(这里的isDel)用来标识是否进行了删除。有代码洁癖的人估计会有点难受。
2.被标记为isDel=true的tree组件依然缓存在内存中并未销毁。如果用户频繁操作,将在内存中占据更多空间。

那么我重新思考新的方案?怎么能让删除的tree销毁掉?sf有相关的帖子,采用了直接去操作this.$vnode.parent.componentInstance.cache;的方案,是可以解决,但是我这里还是暂时不考虑,毕竟觉得这个方案有点剑走偏锋。所以我又回到了官方的文档中,有没有可能采用动态组件(其实我上面的方案也类似动态组件,只不过组件名称都是相同的)的方案去解决呢?配合keep-alive的include的和exclude去更完美的去解决这个问题?这里有个关键点就是include的和exclude,但是看下官方关于这2个属性的描述,看到了什么?name,组件名称。
图片描述

但是我的业务和上面的代码已经明确就只有一个组件就是tree组件,那么我们怎么动态去创建多个名字?动态组件,is主要是感觉组件名称去进行切换的,那么有一个最致命的问题,就是我这个组件命要怎么创建(这句话听起来有点懵吧)?
我们先来看看正常的情况
图片描述

这里特殊说明一下,我使用的是单文件组件,非单文件组件的方式不再此讨论(例如这个不是在此谈论https://jsfiddle.net/jingkaiz...

可以从截图中看到,一开始在components属性中就已经注册了可用的组件名称和对应的组件,那么此处如何才能在用户添加tab的事件中动态的给components属性添加一个新的组件?其实还是tree组件,但是要做一个深度拷贝,这样保证它保存的状态是和新创建的tab是唯一对应的。但是名字要怎么弄?思路到此,就断了,求大神帮忙

阅读 2.6k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题