vue自定义keepalive组件

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

为什么会出现这种情况呢

keep-alive组件是使用 include exclude这两个属性传入组件名称来确认哪些可以被缓存的

    <keep-alive exclude="a,b,c" >
<router-view></router-view>
</keep-alive>

我们在看一下源码,看看人家是怎么实现的(这两张图截的真难看)


主要逻辑(只说上述代码)就是根据传入的 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的作用是用来区分同一个组件是不是重复使用一个实例。

vue 自己实现一套 keepalive 方案的更多相关文章

  1. vue中遇到的坑keep-alive、vue-router相关

    在进入详情页之后,然后返回到首页,报错如下.  虽说是报错了,但是对我最后的页面并没有什么影响,但是出现了一堆红色的报错,作为一个前端工程师,看着还是十分难受的!! 一旦出现问题,我的解决思路一般是, ...

  2. spring junit 部署两套测试方案

    第一套方案: 1.初始化application:使用@ContextConfigurationr的classpath属性,如 @ContextConfiguration(locations = { & ...

  3. Vue源码解析,keep-alive是如何实现缓存的?

    前言 在性能优化上,最常见的手段就是缓存.对需要经常访问的资源进行缓存,减少请求或者是初始化的过程,从而降低时间或内存的消耗.Vue 为我们提供了缓存组件 keep-alive,它可用于路由级别或组件 ...

  4. 结合Vue.js的前端压缩图片方案

    这是一个很简单的方案.嗯,是真的. 为什么要这么做? 在移动Web蓬勃发展的今天,有太多太多的应用需要让用户在移动Web上传图片文件了,正因如此,我们有些困难必须去攻克: 低网速下上传进度缓慢,用户体 ...

  5. vue的两种服务器端渲染方案

    作者:京东零售 姜欣 关于服务器端渲染方案,之前只接触了基于react的Next.js,最近业务开发vue用的比较多,所以调研了一下vue的服务器端渲染方案. 首先:长文预警,下文包括了两种方案的实践 ...

  6. Java中的四套读写方案

    一.字节流读写方案 FileInputStream:字节流方式读取文本文件 FileoutputStream:字节流写入硬盘 二.字符流读写方案 FileReader:字符流读取文本 FileWrit ...

  7. VUE 内置的标签<keep-alive></keep-alive>作用

    <keep-alive></keep-alive> 的作用是 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染组件

  8. Laravel+vue实现history模式URL可行方案

    项目:laravel + vue 实现前后端分离.vue-router 默认 hash 模式 -- 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载. h ...

  9. vue 单页面应用 app自适应方案

    本文是使用淘宝的方案进行布局开发的,遇到的问题是会对app内使用的第三方插件,当页面进行缩放后,比如高德地图中的文字会显得过小,我使用的方法就是手动的动每一个尺寸进行手动的px 到 rem的替换,而不 ...

  10. 永远不要眼高手低,Vue完整实现一套简单的增删改查CURD操作

    1: 永远不要眼高手低,看起来很简单,但是你从来没有去动手试一下,就不知道其中真正需要注意的许多细节, 2:完整code如下: 1 <!DOCTYPE html> 2 <html l ...

随机推荐

  1. 阿里巴巴为什么建议使用BigDecimal进行浮点数运算

    本文先引入一个例子,星期天你和女朋友去逛街,看到一家奶茶店.女朋友想喝奶茶了,你就去买了杯奶茶,然后你问了一下价格.店员说奶茶0.9元一杯.然后你给了1元钱.这个时候你忽然问了一下女友.服务员该找我们 ...

  2. ES(ECMAScript)标准下中的let、var和const

    ES标准下中的let,var和const let会报重复声明,var则比较随意,重不重复无所谓 // 使用 var 的时候重复声明变量是没问题的,只不过就是后面会把前面覆盖掉 var num = 10 ...

  3. 《HelloTester》第4期

    1.前言 终于到了谈面试的部分了! 我在这也说明一下,有同学说之前简历篇的时候一直在说项目的介绍,而面试官真正关心的是技术啊?我在这做个解释,因为我写的这些文章主要针对的是软件测试的同学,所以其他职位 ...

  4. MYSQL5.7.30安装

    1.下载MySQL 我用的是5.7.30(安装版) 我选择的下载链接:https://dev.mysql.com/downloads/windows/installer/5.7.html 官网链接:h ...

  5. C++ sizeof与strlen,并借此明晰内存对齐

    前言 sizeof()与strlen()都是为了获取对象的长度.在正常编写C++的算法程序代码时,可能这两个都很少用到,因为各种stl容器的封装已经给了我们很大的便利,比如我们在想要获取自定义的vec ...

  6. 通过命令快速找到python的路径

    查询Python 首先我们需要知道Python安装路径,可以在命令行中逐行执行下面代码 python3 import sys sys.executable

  7. 重复delete 对象指针后的 异常调用栈怪异 解析

    Release版VC6 MFC程序 程序正常退出时得到一个如下异常调用栈: 0:000> kb # ChildEBP RetAddr Args to Child WARNING: Frame I ...

  8. 记一次 .NET 某外贸ERP 内存暴涨分析

    一:背景 1. 讲故事 上周有位朋友找到我,说他的 API 被多次调用后出现了内存暴涨,让我帮忙看下是怎么回事?看样子是有些担心,但也不是特别担心,那既然找到我,就给他分析一下吧. 二:WinDbg ...

  9. Django框架——可视化界面之数据增删改查、Django请求生命周期、Django路由层、反向解析

    可视化界面之数据增删改查 针对数据对象主键字段的获取可以使用更加方便的 obj.pk获取 在模型类中定义双下str方法可以在数据对象被执行打印操作的时候方便的查看 ''' form表单中能够触发调剂动 ...

  10. node.js基于react项目打包部署到nginx中(Linux服务器)

    1.首先进入React项目目录. 2.执行npm命令进行打包(生成dist包或build包). npm run build 3.将打包的静态文件放入nginx目录中(可以自己新创建一个目录,也可以放在 ...