2022-11-02 vue3+ECharts多个组件循环使用resize失效问题

image.png

功能需求:同样的图表组件,数据不同,父组件利用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>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容