Vue 全站缓存之 keep-alive : 动态移除缓存

阅读本文以前,默认你们对 vue 和 keep-alive 都很熟悉,因此再也不啰嗦相关资料,直接进入正文。javascript

有耐心的话,且听我细细道来,若是你遇到过相似问题,或正在寻找解决方案,那么你能够直接翻到文末看结论。html

本篇为系列篇1:Vue 全站缓存之 keep-alive : 动态移除缓存vue

系列篇2:Vue 全站缓存二:如何设计全站缓存java

系列篇3:Vue 全站缓存之 vue-router-then :先后页数据传递node

系列篇4:Vue 全站缓存之 vue-router-then :实现原理git

前言

以一个记帐项目举例,常见的场景有首页、记到帐页面、选择合同、新建合同、选择客户、新建客户这些页面。github

在这些页面中,很显然,用户的浏览行为应该是逐渐深刻的,通俗得讲就是浏览页面在不断前进。vue-router

并且这些页面之间仍是有互动性存在的,两种互动行为:vuex

  • 一. 用户前进时,老是进入新的页面。(好比在合同列表页反复加载屡次列表以后,进入其中一个合同详情,再返回时,应该仍停留以前里列表页同一个位置,而不是从新刷新列表页。)
  • 二. 用户后退时,须要能保留前一页数据并继续操做。(好比,记到帐时须要选择合同,选择合同时能够新建合同,新建合同时填了一堆数据能够去选择客户,在选择客户时又去建立了客户,那么这一堆操做下来应该可以作到:建立完客户后继续新建合同,建完合同后继续记该合同的到帐

上图是 demo 项目中的真实效果,目前常见的 vue 开发方案里,通常都会引入 vuex 或 localStorage ,在各个页面不断的存储和调用页面内的数据,我以为,这很不科学很不优雅api

keep-alive 什么问题

vue 支持 keep-alive 组件,若是启用,页面内的全部数据都会被保留,因此,上文的互动行为二后退时保留前一页数据继续操做没有问题。

问题出在互动行为一用户前进时老是进入新页面,然而一旦缓存,你就无法老是进新页面了,你老是进入缓存页,这就很让人头疼了。

官方提供了includeexclude特性,说你能够决定哪些页面使用缓存哪些页面不用缓存。连接

然而问题又回到了原点,并无解决咱们酌情决定是否使用已缓存的缓存这一需求。

因此不少人想到了一个方法在离开页面时销毁这个页面是否是就能够了,然而并不能,这里出现了 bug ,组件销毁了缓存还在:

因而,就有人提出但愿keep-alive能增长能够动态删除已缓存组件的功能issue

这是个老话题,以前一直没有进展,核心缘由就在于 keep-alive 不能正确处理已销毁的组件。

尝试解决这个问题

若是能实现动态使用缓存这一功能,那么全部问题也就迎刃而解。

最初,我研究 keep-alive 的代码,发现了这么一段代码:

因而,我想,若是在此处判断若是组件已被销毁则不使用缓存,是否是就解决这个问题了,因而我提交了一个 PR:

不过这个 PR 迟迟没有经过,我就放弃了。

暴力解决这个问题

我继续研究有没有其余方案,而后我在打印组件变量的时候,发现了这么个眼熟的字段:

这不就是 keep-alive 的组件嘛,我赶紧点开再看,发现了更眼熟的东东:

因而,这事儿就变得简单了,直接按图索骥,咱在销毁组件以前,寻找路由组件所在父级的 keep-alive 组件,操控其中的 cache 列表,强行删除其中的缓存,问题也就迎刃而解,是否是很直接很暴力。

结论

keep-alive 默认不支持动态销毁已缓存的组件,因此此处给出的解决方案是经过直接操控 keep-alvie 组件里的 cahce 列表,暴力移除缓存:

//使用Vue.mixin的方法拦截了路由离开事件,并在该拦截方法中实现了销毁页面缓存的功能。
Vue.mixin({
    beforeRouteLeave:function(to, from, next){
        if (from && from.meta.rank && to.meta.rank && from.meta.rank>to.meta.rank)
        {//此处判断是若是返回上一层,你能够根据本身的业务更改此处的判断逻辑,酌情决定是否摧毁本层缓存。
            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();
    },
});
复制代码

后语

本文主要围绕如何动态删除 keep-alive 缓存这一问题进行探索,其余关于如何设定页面层级、如何在先后页之间进行数据传递等问题,敬请期待《Vue 全站缓存之 vue-router-then :先后页数据传递》。

请继续阅读-系列篇2:Vue 全站缓存二:如何设计全站缓存

原文来自阿星的博客:wanyaxing.com/blog/201807…

相关文章
相关标签/搜索