Echart 实例未销毁,内存泄漏问题

vue3 中使用 Echart 时,通常会在组件挂载时完成实例的初始化,下面是个简单实现方法

<template>
  <div ref="chartContainer" :style="{ width: '100%', height: '400px' }"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
const chartContainer = ref(null)
const getChartOption = () => {
  return {
    title: {
      text: '简单柱状图'
    },
    tooltip: {},
    xAxis: {
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    },
    yAxis: {},
    series: [
      {
        name: '销量',![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b28c016d9846430a9802230e0e4c7265.png#pic_center)

        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
      }
    ]
  }
}
onMounted(() => {
  const chartInstance = echarts.init(chartContainer.value) //初始化echarts实例
  chartInstance.setOption(getChartOption()) //设置图表配置项
  
  //监听窗口大小变化, 重新设置图表大小
  window.addEventListener(
    'resize',
    () => chartInstance.resize(),
    false
  )
})
</script>

很显然,这个组件功能是实现了,当组件销毁时,却没有销毁Echart实例,这样会导致内存泄漏。

改进:

在组件内定义一个变量,用于存储echart实例,这样就可以在onUnmounted中访问到实例,然后对实例进行销毁,对于添加的事件监听,可以定义一个具名函数,方便在组件销毁时移除事件监听。

addEventListener方法第二个参数是接受一个函数引用,如果使用匿名函数则不能正确的移除事件监听,如()=> chartInstance.resize(),这样每次访问时引用都不一样,清不掉,根本清不掉。当然也可以直接传 chartInstance.resize

<template>
  <div ref="chartContainer" :style="{ width: '100%', height: '400px' }"></div>
</template>

<script setup>
let chartInstance = null
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
const chartContainer = ref(null)
const getChartOption = () => {
  return {
    title: {
      text: '简单柱状图'
    },
    tooltip: {},
    xAxis: {
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    },
    yAxis: {},
    series: [
      {
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
      }
    ]
  }
}

const handleResize = () => {
  if (chartInstance) {
    chartInstance.resize()
  }
}
onMounted(() => {
  chartInstance = echarts.init(chartContainer.value) //初始化echarts实例
  chartInstance.setOption(getChartOption()) //设置图表配置项
  
  //监听窗口大小变化, 重新设置图表大小
  window.addEventListener(
    'resize',
    handleResize,
    false
  )
})
onUnmounted(() => {
  //监听窗口大小变化, 重新设置图表大小
  window.removeEventListener(
    'resize',
    handleResize,
    false
  )

  if (chartInstance) {
    chartInstance.destroy() //销毁实例
    chartInstance = null
  }
})
</script>

这样就能在组件销毁时对echart实例进行销毁以及移除事件监听,防止内存泄漏。还有的就是如果echart实现了轮播功能,一定要存一下定时器的id,以便清除定时器。

这都是接手别人项目遇到的一些问题,测试反应项目越用越卡,然后去检查了下,发现项目用到的echart都没有手动进行销毁、以及事件监听都没有移除,且这个项目主要是大屏,基本每一个页面都是echart,在解决这个过程中还发现了一些定时器没有清除,定时器被埋在初始化图的方法中,在销毁组件实例后(此时已经销毁Echart实例,以及事件监听),控制台满屏警告,如图:
在这里插入图片描述

应该是定时器访问不到实例上的方法了,清除掉定时器就解决了。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值