如何在Vue 3中使用vue-chartjs 5.2从父组件更新图表。

huangapple go评论59阅读模式
英文:

How to update charts from parent in vue3 with vue-chartjs 5.2

问题

我是新手使用 Vue,老实说我不太明白如何从其父级更新图表。通过 vue-dev-tools,我看到数据已经更新,但没有触发图表更新。
我发现了很多关于 vue2 和旧的 vue-chartjs API 调用的过时信息,以及针对 vue-chartjs 新 API 的文档,但这些都没有帮助我。vue-chartjs 表示有数据监视器。所以我假设,当我改变数据时,图表会更新。但我感觉我在这里漏掉了什么。

Codesandbox: https://codesandbox.io/s/v8rdgz

我正在使用 Vue3 和

vue-chartjs@5.2.0
chart.js@4.3.0

我尝试了 props、computed、refs,但没有达到我的目标。
以下是我的最小示例。当按下“更新图表”按钮时,应该出现另一条线。

// LineChart.vue
<template>
  <Line :data="data" :options="options" />
</template>

<script>
import { Line } from "vue-chartjs";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from "chart.js";

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
);

export default {
  components: { Line },
  props: ["data", "options"],
};
</script>
// App.vue
<template>
  <div>
    <button @click="updateGraph">Update Graph</button>
  </div>
  <div>
    <LineChart :data="chartData" :options="chartOptions" />
  </div>
</template>

<script>
import LineChart from "./components/LineChart.vue";

export default {
  data() {
    return {
      chartData: {
        labels: [
          "January",
          "February",
          "March",
          "April",
          "May",
          "June",
          "July",
        ],
        datasets: [
          {
            label: "Data One",
            backgroundColor: "#f87979",
            data: [40, 39, 10, 40, 39, 80, 40],
          },
        ],
      },
      chartOptions: {
        responsive: true,
        maintainAspectRatio: false,
      },
    };
  },
  components: {
    LineChart,
  },

  methods: {
    updateGraph() {
      this.chartData.datasets.push({
        label: "Data Two",
        backgroundColor: "#f87979",
        data: [50, 59, 50, 50, 59, 50, 50],
      });
    },
  },
};
</script>

提前感谢您!
最好的祝愿。

英文:

I'm new to vue and to be honest I don't understand how I can update a graph from its paren. With the vue-dev-tools I see that the data got updated, but doesn't trigger a graph update.
I find a lot of out-dated information for vue2 and older vue-chartjs api calls + the documentation for the new api for vue-chartjs, which doesn't help me. The vue-chartjs says that there are data watchers. So I assume, when I change the data, the graph updates. But something I'm missing here.

Codesandbox: https://codesandbox.io/s/v8rdgz

I'm using vue3 with

vue-chartjs@5.2.0
chart.js@4.3.0

I fiddled around with props, computed, refs but I didn't achieve my goal.
Here my minimal example. When the Update Graph Button is pressed. There should appear another line., another line should appear.

// LineChart.vue
&lt;template&gt;
  &lt;Line :data=&quot;data&quot; :options=&quot;options&quot; /&gt;
&lt;/template&gt;

&lt;script&gt;
import { Line } from &quot;vue-chartjs&quot;;
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from &quot;chart.js&quot;;

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
);

export default {
  components: { Line },
  props: [&quot;data&quot;, &quot;options&quot;],
};
&lt;/script&gt;

// App.vue
&lt;template&gt;
  &lt;div&gt;
    &lt;button @click=&quot;updateGraph&quot;&gt;Update Graph&lt;/button&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;LineChart :data=&quot;chartData&quot; :options=&quot;chartOptions&quot; /&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
import LineChart from &quot;./components/LineChart.vue&quot;;

export default {
  data() {
    return {
      chartData: {
        labels: [
          &quot;January&quot;,
          &quot;February&quot;,
          &quot;March&quot;,
          &quot;April&quot;,
          &quot;May&quot;,
          &quot;June&quot;,
          &quot;July&quot;,
        ],
        datasets: [
          {
            label: &quot;Data One&quot;,
            backgroundColor: &quot;#f87979&quot;,
            data: [40, 39, 10, 40, 39, 80, 40],
          },
        ],
      },
      chartOptions: {
        responsive: true,
        maintainAspectRatio: false,
      },
    };
  },
  components: {
    LineChart,
  },

  methods: {
    updateGraph() {
      this.chartData.datasets.push({
        label: &quot;Data Two&quot;,
        backgroundColor: &quot;#f87979&quot;,
        data: [50, 59, 50, 50, 59, 50, 50],
      });
    },
  },
};
&lt;/script&gt;

Thank you in advance!!!
Best regards

答案1

得分: 1

问题是您进行的更新太深。您需要用更新后的 chartData 替换,而不是简单更新其 datasetschart.js 支持对 datasets 数组进行变异,但 Vue 不会深度监视数据更新。所以除非您替换 this.chartData,否则 Vue 不会更新 Line.vue,它在 LineChart.vue 内部使用。

  this.chartData = {
    ...this.chartData,
    datasets: [
      ...this.chartData.datasets, {
        label: "Data Two",
        backgroundColor: "#f87979",
        data: [50, 59, 50, 50, 59, 50, 50],
      }
    ]
  }
}```

[演示链接](https://codesandbox.io/s/competent-leftpad-s72lm7?file=/src/App.vue).

或者,您可以告诉 Vue 何时需要重新呈现组件,使用 `:key="chartData.datasets.length"` 在您的 `<LineChart />` 组件上。然而,这种方法会从头开始重新渲染图表,因此您将得到初始数据的动画,而不是从旧数据状态到新数据状态的动画。

我推荐第一种方法。

<details>
<summary>英文:</summary>

The problem is the update you&#39;re making is too deep. You need to replace `chartData` with an updated version of itself, instead of simply updating its `datasets`. `chart.js` does support mutating the `datasets` array, but Vue does not watch data updates deeply. So unless you replace `this.chartData`, Vue won&#39;t update `Line.vue`, used internally by `LineChart.vue`.

updateGraph() {
  this.chartData = {
    ...this.chartData,
    datasets: [
      ...this.chartData.datasets, {
        label: &quot;Data Two&quot;,
        backgroundColor: &quot;#f87979&quot;,
        data: [50, 59, 50, 50, 59, 50, 50],
      }
    ]
  }
}
[Working demo](https://codesandbox.io/s/competent-leftpad-s72lm7?file=/src/App.vue).
___

Alternatively, you can tell Vue when the component needs to be re-rendered, by using `:key=&quot;chartData.datasets.length&quot;` on your `&lt;LineChart /&gt;` component. However, this method re-renders the chart from scratch, so you&#39;ll get the initial data animations, not the ones from old data state to new data state. 

I recommend the first method.

</details>



huangapple
  • 本文由 发表于 2023年6月22日 16:30:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529958.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定