J'utilise Vue.js et Chart.js pour dessiner un graphique. Chaque fois que j'appelle la fonction generateChart()
, le graphique n'est pas mis à jour automatiquement. Lorsque je vérifie les données dans le VueDevTools
, elles sont correctes mais le graphique ne les représente pas.
Fait amusant: le graphique est mis à jour lorsque je redimensionne la fenêtre.
generateChart()
?Je pense que cela va être lié à object
et array
change la mise en garde de détection, mais je ne sais pas quoi faire.
https://codepen.io/anon/pen/bWRVKB?editors=101
<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;
}
import { Line, mixins } from 'vue-chartjs'
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ["options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
Utilisez une propriété calculée pour les données du graphique. Et au lieu d'appeler this.renderChart
on watch envelopper dans une méthode et réutiliser cette méthode sur mounted
et dans 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>
Vous pouvez également faire des options une propriété calculée et si l'option ne change pas beaucoup, vous pouvez configurer les accessoires par défaut. https://vuejs.org/v2/guide/components.html#Prop-Validation
Voici un codepen de travail https://codepen.io/azs06/pen/KmqyaN?editors=101
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)
}
}
ajouter un observateur personnalisé pour mettre à jour tout graphique de graphique vue
Je n'ai jamais utilisé vue-chartjs auparavant, mais il semble que votre seul problème est que vous avez oublié de recevoir explicitement chartData comme accessoire dans votre composant graphique en ligne:
Changement
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ["options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
avec
export default Line.extend({
mixins: [mixins.reactiveProp],
props: ["chartData", "options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
Aussi, soyez conscient des problèmes de réactivité vue lors du changement d'objets, cela ne fonctionnera pas:
this.dataChart['datasets'] = datasets;
vous devez faire quelque chose comme ça:
Vue.set(this.dataChart, 'datasets', datasets);
dans l'ordre Vue pour détecter les changements dans votre objet.
Plus d'informations sur la réactivité: https://vuejs.org/v2/guide/reactivity.html
Plus d'informations sur la réactivité dans les graphiques: http://vue-chartjs.org/#/home?id=reactive-data