英文:
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
<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>
Thank you in advance!!!
Best regards
答案1
得分: 1
问题是您进行的更新太深。您需要用更新后的 chartData
替换,而不是简单更新其 datasets
。chart.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'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't update `Line.vue`, used internally by `LineChart.vue`.
updateGraph() {
this.chartData = {
...this.chartData,
datasets: [
...this.chartData.datasets, {
label: "Data Two",
backgroundColor: "#f87979",
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="chartData.datasets.length"` on your `<LineChart />` component. However, this method re-renders the chart from scratch, so you'll get the initial data animations, not the ones from old data state to new data state.
I recommend the first method.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论