资讯专栏INFORMATION COLUMN

vue 里主动销毁 keep-alive 缓存的组件

antz / 3222人阅读

摘要:经过网上一翻查找,发现销毁一个组件可以使用组件名来销毁。本质上是把整个节点及对应的事件等都缓存下来了,当这样的组件很多的时候,自然会占用很多内存。

问题产生的背景

我们一个后台,在切换一些标签页的时候,是使用的 keep-alive 缓存的标签页,也使用了 include 属性来决定哪个页面进行缓存,而标签页的切换实际上是路由的切换,也就是说打开一个新标签页的时候,url 会跟着变化,老的标签页如果在 keep-aliveinclude 范围内那就会缓存下来。
然后客服人员就反馈页面开的久了就会崩溃,因为他们基础上不会刷新页面(工作需要),又总有切换标签的习惯,最后导致内存越来越大最后崩溃。

依赖环境

这个项目是基于一个开源 vue 后台框架:https://github.com/PanJiaChen/vue-element-admin,然后代码一直由几个后端开发维护的!所以后端没找出问题在哪,然后就我来接手这个问题了。
写文章时,标签里竟然没有 vue 这一项,差评!

定位问题

先梳理下业务逻辑:从业务场景来说,我们在标签页之间切换时,如果刚进入的这个标签页已被缓存了,那被缓存的标签页就直接拿出来展示就行,而关闭这个标签页的时候就应该销毁对应的组件。

花了点时间查看了一下代码,发现问题在于关闭标签页的时候,虽然这个页面没在 keep-aliveinclude 里了,但是组件也没有被销毁掉,还是在缓存状态,我们可以通过 Vue Devtools 插件看到关闭后的标签页对应的组件一直还存在着:

当然,在这块 keep-alive 本身的逻辑我觉得是没问题的,主要是我们项目比较复杂,缓存的组件太多了而且会一直增加,所以最终导致崩溃。

解决问题

既然问题已经定位了,那就好解决问题了,只需要在关闭标签页的时候把对应的组件也销毁掉就好了。

经过网上一翻查找,发现销毁一个组件可以使用: this.$destroy(‘组件名’) 来销毁。

先说下大概思路:keep-aliveinclude 里存的其实是一个 vuex 中的一个数据源(数据源保存的是路由名称),当关闭标签页时,这个数据源中的一项会被移除。这之前,我们在组件里监听到这个数据源的变化,如果此组件对应的路由(这个路由应在 mounted 的时候保存下来)已经不在数据源中了,那就应该销毁此组件。

代码大概如下:

const mixin = {
  data() {
    return {
      routePath: ""
    }
  },
  mounted() {
    this.routePath = this.$route.path
  },
  computed: {
    visitedViews() {
      return this.$store.state.tagsView.visitedViews
    }
  },
  watch: {
    visitedViews(value) {
      if(value 里没有了 routePath 这一项)
        this.$destroy(this.$options.name)
      }
    }
  }
}

export default mixin

这一段代码多带带拎出来了,然后在需要缓存的组件里使用 mixins 混入到组件对象中,这样组件中要添加的代码量就比较少了。

更改后经过测试,关闭标签页后对应的组件就会被销毁掉,使用 Vue Devtools 能看的很清楚。

更多思考

在我们后台操作这么频繁的业务场景下,使用 keep-alive 其实并不是一个好的选择。

在我们修复这个问题后,我们通过控制台里的 Memory 查看页面内存的变化时,发现组件即便被销毁,也要经过一段时间才能回收完,当我们在这一段时间一直创建/打开新的标签页时,内存还是会在短时间内高涨。而且有时候,内存在经过一段时间后也并没有回收掉。

keep-alive 本质上是把整个 dom 节点及对应的事件等都缓存下来了,当这样的组件很多的时候,自然会占用很多内存。而如果我们只缓存这个组件中的数据,在需要这个组件再次显示的时候再临时渲染那肯定要节省很多内存的,毕竟数据占的空间其实很小的,而渲染组件要花的时间也不会很长(只要组件不是特别特别复杂)。

所以,下一阶段的优化工作就是把 keep-alive 去掉,然后使用 vuex 来缓存组件中的数据,当需要重新显示数据时再把数据取出来并重新渲染。当然,这是一个比较大的工程!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102739.html

相关文章

  • vue中keepAlive使用

    摘要:文档在及其更高版本中,和将会在树内的所有嵌套组件中触发。另外,在我们的项目中遇到路由相同但参数不同的情况组件被复用,不更新的问题,官方给出了响应路由参数变化根据参数数据响应 前言 在开发中经常有从列表跳到详情页,然后返回详情页的时候需要缓存列表页的状态(比如滚动位置信息),这个时候就需要保存状态,要缓存状态;vue里提供了keep-alive组件用来缓存状态。可以用以下几种方案解决问题...

    Anleb 评论0 收藏0
  • 个人 vue 项目优化总结

    摘要:很多优化点都是根据实际情况入手,上面这几个,都是我在做项目时,感觉不合适而进行优化的,后面会持续补充下去 主要说的是,我在项目中,自己遇到的一些小问题和解决方案 图片 base64 问题 // 有一个 test 的组件 .icon { background: url(../assets/test.png); } // 然后有三个页面,引入了 test 组...

    taoszu 评论0 收藏0
  • vue keep-alive组件使用以及原理。

    摘要:通过这两种方式分别检测是否匹配当前组件。修正取出中的不符合条件的,同时不是目前渲染的时,销毁对应的组件实例实例,并从中移除销毁对应的组件实例实例遍历中的所有项,如果不符合指定的规则的话,则会执行。则会调用组件实例的方法来将组件销毁。 keep-alive keep-alive是vue.js的内置组件,它能够把不活动的组件的实例保存在内存中,而不是直接的销毁,它是一个抽象组件,不会被渲染...

    pingan8787 评论0 收藏0
  • 聊聊keep-alive组件使用及其实现原理

    摘要:为的组件将不会被缓存。通过这两种方式分别检测是否匹配当前组件。修正取出中的不符合条件的,同时不是目前渲染的时,销毁对应的组件实例实例,并从中移除销毁对应的组件实例实例遍历中的所有项,如果不符合指定的规则的话,则会执行。 写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出。 文章的原地址:http...

    frolc 评论0 收藏0
  • vue keep-alive实现动态缓存以及缓存销毁

    摘要:实现动态缓存以及缓存销毁需求来源及描述后台管理系统中,左侧为功能菜单栏,点击菜单列表,右侧显示该菜单的功能页面,本来是一个非常简单的后台管理系统布局,现在增加了菜单按钮点击左侧菜单栏时,右侧页面头部显示当前的页面标题,形成一个列表,点击可 vue keep-alive实现动态缓存以及缓存销毁 需求来源及描述 后台管理系统中,左侧为功能菜单栏,点击菜单列表,右侧显示该菜单的功能页面,本来...

    littleGrow 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<