You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

vue-chart.js多实例初始化异常:多图表同步显示非对应传感器数据问题排查

问题诊断与解决方案

我一眼就看出问题所在了——你踩了引用类型共享的经典Vue坑!

问题根源

  1. 全局配置对象共享引用:你在组件外部定义了const chartSetting = {...},这是一个全局对象。由于对象是引用类型,所有Test组件实例都会共享同一个data.datasets[0].data数组。不管哪个组件调用adddata,都是在修改同一个数组,自然两个图表会显示相同的数据。
  2. 全局定时器变量冲突:你用了全局的interval变量,当第二个组件挂载时会覆盖第一个组件的定时器引用,虽然这不是当前数据混乱的主因,但会导致第一个组件的定时器无法正确清除,属于潜在的内存泄漏风险。

修复步骤

  1. 为每个组件实例创建独立的图表配置:把图表配置移到组件的data函数里,让每个实例都拥有自己的数据集数组。
  2. 将定时器变量纳入组件实例管理:把interval放到组件的data中,避免全局覆盖,同时在组件销毁时清除定时器。
  3. 组件销毁时清理资源:销毁Chart实例并清除定时器,防止内存泄漏。

修改后的代码

Test.vue

<template>
  <div>
    <canvas :id="name"></canvas>
  </div>
</template>
<script>
import Chart from "chart.js";

export default {
  name: "test",
  data() {
    return {
      myChart: null,
      interval: null,
      // 每个组件实例都生成独立的配置副本
      chartSetting: {
        type: "line",
        data: {
          datasets: [
            {
              label: "setpoint",
              data: [],
              borderColor: "blue",
              borderWidth: 3,
            },
          ],
        },
        options: {},
      },
    };
  },
  props: ["id", "name", "setpoint"],
  methods: {
    adddata(setpoint, time) {
      this.myChart.data.datasets[0].data.push(setpoint);
      this.myChart.data.labels.push(time);
      this.myChart.update();
      console.log(`now printing ${setpoint} to this graph:`);
      console.log(this.myChart);
    },
    createChart(chartId, chartData) {
      const ctx = document.getElementById(chartId);
      this.myChart = new Chart(ctx, {
        type: chartData.type,
        data: chartData.data,
        options: chartData.options,
      });
      // 使用实例内的定时器变量,避免全局冲突
      this.interval = setInterval(() => {
        let date = new Date();
        let seconds = date.getSeconds();
        this.adddata(this.setpoint, seconds);
      }, 5000);
    },
  },
  mounted() {
    this.createChart(this.name, this.chartSetting);
  },
  // 组件销毁时清理资源
  beforeUnmount() {
    if (this.interval) clearInterval(this.interval);
    if (this.myChart) this.myChart.destroy();
  },
};
</script>

App.vue(保持原代码即可)

<template>
  <div id="app">
    <p> graphs get new data from 2 different sensors every 5 seconds. Here simulated as "6" and "3" </p>
    <h3>this graph should only show 6</h3>
    <test name="grap1" id="1" setpoint="6" />
    <h3>this graph should only show 3</h3>
    <test name="grap2" id="2" setpoint="3" />
  </div>
</template>
<script>
import Test from "./components/Test";
export default {
  name: "App",
  components: {
    Test,
  },
};
</script>

修复原理说明

  • 每个组件实例的chartSetting.data.datasets[0].data都是独立的数组,不再共享引用,所以添加数据只会作用于当前图表。
  • 定时器变量属于组件实例,不会被其他实例覆盖,组件销毁时能正确清理,避免内存泄漏。
  • 销毁Chart实例是好习惯,防止DOM元素移除后残留的Chart对象占用资源。

内容的提问来源于stack exchange,提问作者Pan Vi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:47:50