功能需求:同样的图表组件,数据不同,父组件利用v-for循环图表组件,传入对应的类型参数
根据ECharts官方文档,当窗口大小变化时,改变图表自适应大小方法:
监听页面的 window.onresize
事件获取浏览器大小改变的事件,然后调用 echartsInstance.resize
改变图表的大小
window.onresize = function() {
myChart.resize();
};
此方法在单个组件中没问题,但是多个组件的情况下就会失效,在 window.onresize的回调方法中打印的myChart实例DOM为最后一个组件,只有最后一个组件可以自适应。
开始我以为是由于ref名重复导致初始化的实例为同一个dom的问题,然后给图表DOM绑定动态的ref名
<div :ref="`${props.componentType}Ref`" class="w-full h-full"></div>
onMounted(() => {
const { $refs } = getCurrentInstance().proxy;
console.log($refs[`${props.componentType}Ref`,"对应的ref"])
...
// 后面就循环初始化配置图表选项等。。。
});
发现给每个组件绑定了不同名的ref也还是没用,经过打印window.onresize回调的执行才发现只执行了一次,打印的图表实例为最后一个组件。
window.addEventListener监听‘resize’方法执行了6次,每次打印的图表实例都是对应的组件 。
原来只需要将 window.onresize 修改为 window.addEventListener('resize',()=>{}) 就解决问题了
最后贴一下完整代码
// 父组件
<template>
<div class="card-content">
<el-row :gutter="24">
<el-col :xl="8" :md="12" :sm="24" v-for="item in typeArr" :key="item">
<my-echarts :componentType="item"></my-echarts>
</el-col>
</el-row>
</div>
</template>
<script setup name="DeviceResource">
import myEcharts from "./echarts.vue";
const typeArr = ref([
"cpu",
"memory",
"sessions",
"new_sessions",
"onlineip",
"onlineuser",
]);
</script>
<style lang="scss" scoped>
.card-content {
padding: 20px;
}
</style>
// 子组件
<template>
<el-card class="grid-content">
<template #header
><b>{{ echartsData.info }}</b>
<div>
<el-button type="text">近一个小时</el-button>
<el-button type="text">近一天</el-button>
</div></template
>
<div ref="echartsRef" class="w-full h-full"></div>
</el-card>
</template>
<script setup name="DeviceResource">
import * as echarts from "echarts";
import { cpuUsageAmount } from "@/api/firewall/index";
const props = defineProps({
componentType: {
type: String,
default: "",
},
});
const echartsData = ref({
data: [],
info: "",
time: [],
type: "",
});
let chartObj = null;
const echartsRef = ref(null);
/**
* 渲染图表
*/
function initRender() {
cpuUsageAmount(props.componentType).then((res) => {
echartsData.value = res;
chartObj = echarts.init(echartsRef.value);
const option = {
xAxis: {
type: "category",
boundaryGap: false,
data: echartsData.value.time,
},
yAxis: { name: `单位(${echartsData.value.type})`, type: "value" },
series: [
{
data: echartsData.value.data,
type: "line",
smooth: true,
},
],
};
option && chartObj.setOption(option);
});
}
initRender();
onMounted(() => {
window.addEventListener("resize", () => {
chartObj && chartObj.resize();
});
});
</script>
<style lang="scss" scoped>
.card-content {
padding: 20px;
.grid-content {
height: 400px;
margin-bottom: 20px;
}
}
</style>