vue自定义keepalive组件

前一阵来了一个新的需要,要在vue我的项目中实现一个多开tab页面的性能,原本心想,这不简略嘛就是一个减少按钮重定向吗?(当然如果这么简略我就不写这个文章了)。很快写完,提交测试。测试大哥很快就提交了一个问题:"你两个tab页拜访同一个链接,怎么还是个联动的呢?"。我擦,这指定是缓存的问题。

为什么会呈现这种状况呢

keep-alive组件是应用 include exclude这两个属性传入组件名称来确认哪些能够被缓存的
    <keep-alive exclude="a,b,c" >        <router-view></router-view>    </keep-alive>
咱们在看一下源码,看看人家是怎么实现的(这两张图截的真难看)

<img src="https://img2022.cnblogs.com/blog/1393523/202207/1393523-20220705171521057-2002902406.png" width="600px" alt="male" />
<img src="https://img2022.cnblogs.com/blog/1393523/202207/1393523-20220705171222906-966344680.png" width="760px" alt="male" />

次要逻辑(直说上述代码)就是依据传入的 include, exclude 两个属性传入数组,依据以后拜访的组件名称判断。咱们雷同链接都拜访同一个组件名称(name)雷同,第二次拜访的时候,链接指向的是同一个组件,因为应用组件的name作为缓存key,此时会被认为是读取缓存操作,就会间接加载缓存并渲染,所以呈现了两个tab页拜访同一个链接,呈现联动状况

如何解决这个问题呢

这个比较简单之前是因为组件name当key导致的,那咱们就不应用组件的name作为key了,改为name+tab的index作为key。

问题晓得了怎么解决呢

graph TB    id2{keepalive是否缓存}-->id6[不须要缓存]    id6-->id5    id2-->id7[须要缓存]    id7-.未缓存.->id3[缓存以后页面-vuex]    id7-.缓存过.->id4[读取缓存-vuex]    id4-->id5[渲染页面]    id3-->id5[渲染页面]    id1[tab1 url]-->id2    id8[tab2 url]-->id2

思路有了撸代码

group-keep-alive.js
function remove(arr, item) {  if (arr.length) {    var index = arr.indexOf(item)    if (index > -1) {      return arr.splice(index, 1)    }  }}function getFirstComponentChild(children) {  if (Array.isArray(children)) {    for (var i = 0; i < children.length; i++) {      var c = children[i]      if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {        return c      }    }  }}function isDef(v) {  return v !== undefined && v !== null}function isAsyncPlaceholder(node) {  return node.isComment && node.asyncFactory}var patternTypes = [String, RegExp, Array]export default {  name: 'keep-alive',  abstract: true,  computed: {    // 这里算是一个伪代码    // 缓存的数组 [{ 'tab1/组件名称':comp, 'tab2/组件名称':comp },{ 'tab1/组件名称':comp, 'tab2/组件名称':comp }]      cacheArray() {      return this.$store.state.xxx.groupCache    },    // 以后选中的分组 例:0/1/2... 这里用来读取cache数组的index    groupIndex() {      return this.$store.state.xxx.groupIndex    }  },  created: function created() {    // 以后tab的缓存    const cache = this.cacheArray[this.groupIndex]    this.cache = cache || Object.create(null)    // TODO 页面初始化事件,后续可触发初始化事件  },  destroyed: function destroyed(to, form) {    // TODO 页面来到事件,后续可触发敞开事件  },  render: function render() {    var slot = this.$slots.default    var vnode = getFirstComponentChild(slot)    var componentOptions = vnode && vnode.componentOptions    // check pattern    var ref$1 = this    var cache = ref$1.cache    const key = `${this.groupIndex}/${componentOptions.Ctor.options.name}`    // 存在key间接读取    if (cache[key]) {      vnode.componentInstance = cache[key].componentInstance    } else {      // 没有进行缓存      cache[key] = vnode    }    // 写入缓存    this.$store.dispatch('setGroupCache', {      cache: this.cache    })    return vnode || (slot && slot[0])  }}

如何应用

意思一下就行了
<group-keep-alive>   <router-view :key="key" />/group-keep-alive>// key肯定要辨别computed: {    key() {      return `${选中index}/${fullpath}`    },}

主题说完了,整点其余的

1. 在group-keep-alive组件中设置了abstract: true,设置以后组件为形象组件,我的李姐:就是一个对下一级(蕴含子元素)事件监听等提前拦挡,从而对下一级进行操作
2. router-view :key="key" 这key的作用是用来辨别同一个组件是不是重复使用一个实例。