Javascript Vue Chart.js - 数据更改时图表不会更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43728332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Vue Chart.js - Chart is not updating when data is changing
提问by Léo Coco
I'm using Vue.js and Chart.js to draw some charts.
Each time I call the function generateChart(), the chart is not updated automatically. When I check the data in Vue Devtools, they are correct but the chart does not reflect the data.
我正在使用 Vue.js 和 Chart.js 绘制一些图表。每次调用该函数时generateChart(),图表都不会自动更新。当我在 Vue Devtools 中检查数据时,它们是正确的,但图表并未反映数据。
Fun fact: The chart is updating when I'm resizing the window.
有趣的事实:当我调整窗口大小时,图表正在更新。
- What is wrong with what I'm doing?
- How do I update the chart each time I call
generateChart()?
- 我在做什么有什么问题?
- 每次调用时如何更新图表
generateChart()?
I feel this is going to be something related with objectand arraychange detection caveats, but I'm not sure what to do.
我觉得这将object与array更改检测警告有关,但我不确定该怎么做。
https://codepen.io/anon/pen/bWRVKB?editors=1010
https://codepen.io/anon/pen/bWRVKB?editors=1010
<el-dialog title="Chart" v-model="showGeneratedChart">
<line-chart :chartData="dataChart"></line-chart>
</el-dialog>
export default{
data (){
const self = this;
return {
dataChart : {
labels : [],
datasets: [{
label: 'label',
backgroundColor: '#FC2525',
data: [0, 1, 2, 3, 4],
}]
}
}
}
generateChart() {
this.dataChart['labels'] = [];
this.dataChart['datasets'] = [];
... compute datasets and formattedLabels
this.dataChart['labels'] = formattedLabels;
this.dataChart['datasets'] = datasets;
}
LineChart.js
折线图.js
import { Line, mixins } from 'vue-chartjs'
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ["options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
回答by azs06
Use a computed property for the chart data. And instead of calling this.renderCharton watch wrap it in a method and reuse that method on mountedand in watch.
对图表数据使用计算属性。而不是调用this.renderChartwatch 将它包装在一个方法中并在mounted和 中重用该方法watch。
Vue.component("line-chart", {
extends: VueChartJs.Line,
props: ["data", "options"],
mounted() {
this.renderLineChart();
},
computed: {
chartData: function() {
return this.data;
}
},
methods: {
renderLineChart: function() {
this.renderChart(
{
labels: [
"January",
"February",
"March",
"April",
"May",
"June",
"July"
],
datasets: [
{
label: "Data One",
backgroundColor: "#f87979",
data: this.chartData
}
]
},
{ responsive: true, maintainAspectRatio: false }
);
}
},
watch: {
data: function() {
this._chart.destroy();
//this.renderChart(this.data, this.options);
this.renderLineChart();
}
}
});
var vm = new Vue({
el: ".app",
data: {
message: "Hello World",
dataChart: [10, 39, 10, 40, 39, 0, 0],
test: [4, 4, 4, 4, 4, 4]
},
methods: {
changeData: function() {
this.dataChart = [6, 6, 3, 5, 5, 6];
}
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Vue.jS Chart</title>
</head>
<body>
<div class="app">
{{ dataChart }}
<button v-on:click="changeData">Change data</button>
<line-chart :data="dataChart" :options="{responsive: true, maintainAspectRatio: false}"></line-chart>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-chartjs.full.min.js"></script>
</body>
</html>
You could also make the options a computed property, and if option not going to change much you can setup default props. https://vuejs.org/v2/guide/components.html#Prop-Validation
您还可以将选项设置为计算属性,如果选项不会发生太大变化,您可以设置默认道具。https://vuejs.org/v2/guide/components.html#Prop-Validation
Here is a working codepen https://codepen.io/azs06/pen/KmqyaN?editors=1010
回答by Shrikant
watch: {
chartData: function (newData, oldData) {
// let ctx = document.getElementById('doughnut-chart').getContext('2d')
// console.log(ctx)
// var chart = new Chart(ctx, {type: 'doughnut', data:, options: self.options})
// // chart.config.data.datasets.push(newData)
// chart.config.options.animation = false
// console.log(chart)
// chart.config.data.datasets.push(newData)
// chart.config.optionsNoAnimation = optionsNoAnimation
// console.log(chart.config.data.datasets.push(newData))
// this.dataset = newData
// chart.update()
// console.log('options', this.data)
console.log('new data from watcher', newData)
this.data.datasets[0].data = newData
this.renderChart(this.data, this.options)
}
}
add custom watcher to update any vue chart graph
添加自定义观察者以更新任何 vue 图表
回答by Gerardo Rosciano
I never used vue-chartjs before, but it looks like your only issue is that you forgot to explicitely receive chartData as a prop in your line-chart component:
我以前从未使用过 vue-chartjs,但看起来您唯一的问题是您忘记在折线图组件中明确接收 chartData 作为道具:
Change
改变
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ["options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
with
和
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ["chartData", "options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
Also, be aware of vue reactivity issues when changing objects, this won't work:
另外,更改对象时请注意 vue 反应性问题,这将不起作用:
this.dataChart['datasets'] = datasets;
you have to do something like this:
你必须做这样的事情:
Vue.set(this.dataChart, 'datasets', datasets);
in order Vue to detect changes in your object.
以便 Vue 检测对象中的变化。
More info about reactivity: https://vuejs.org/v2/guide/reactivity.html
有关反应性的更多信息:https: //vuejs.org/v2/guide/reactivity.html
More info about reactivity in charts: http://vue-chartjs.org/#/home?id=reactive-data
有关图表中反应性的更多信息:http: //vue-chartjs.org/#/home?id=reactive-data
回答by óscar García
My solution is without mixins and using a watch to the prop.
我的解决方案是不使用 mixins 并在道具上使用手表。
watch: {
chartData: function() {
this.renderChart(this.chartData, this.options);
}
}
But, this don't work until I change the chartData in another component like this:
但是,直到我像这样在另一个组件中更改 chartData 之后,这才起作用:
this.chartData = {
labels: [],
datasets: []
};
this.chartData.labels = labels;
this.chartData.datasets = datasets;
If I just replace the labels and datasets, the watch won't fired.
如果我只是替换标签和数据集,手表就不会触发。

