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实例,以及事件监听),控制台满屏警告,如图:
应该是定时器访问不到实例上的方法了,清除掉定时器就解决了。