Vue 3 中,响应式状态都被封装为一个 Proxy 实例。如果状态本身也是一个对象,Vue 会默认同时代理其属性(利用 Proxy 特性)。你的代码 this.chart.setOption、this.chart.resize 访问的实际上是被 Vue proxy 代理出来的属性。这里应该出现了引用问题,导致 ECharts 实例的某个方法调用失败。
解决办法
<template>
<div class="echarts" ref="chart" />
</template>
<script >
import * as echarts from "echarts";
let chart = {};
export default {
name: "chart",
data() {
return {
resizeTimer: null,
version: "1.0",
chartTemp: null,
};
},
props: {
// 图表参数
options: Object,
initOptions: Object,
},
options: {
deep: true,
handler(options) {
if (Object.prototype.toString.call(options) === "[object Object]") {
this.setOption(options);
}
},
},
methods: {
// 初始化
init() {
const { options, initOptions } = this.$props;
if (chart[this.chartTemp]) {
chart[this.chartTemp].dispose();
chart[this.chartTemp] = null;
}
chart[this.chartTemp] = echarts.init(
this.$refs.chart,
{},
initOptions
);
if (options) {
chart[this.chartTemp].setOption(options);
}
},
// 调整尺寸
resize(options = {}) {
this.resizeTimer = clearTimeout(this.resizeTimer);
this.resizeTimer = setTimeout(() => {
this.init()
}, 300);
},
},
mounted() {
this.chartTemp = Math.random();
this.$nextTick(() => {
this.init();
});
window.addEventListener("resize", this.resize);
},
beforeUnmount() {
if (chart[this.chartTemp]) {
window.removeEventListener("resize", this.resize);
this.resizeTimer = clearTimeout(this.resizeTimer);
chart[this.chartTemp].dispose();
chart[this.chartTemp] = null;
}
},
};
</script>
<style scoped>
.echarts {
position: relative;
}
</style>