繁体   English   中英

Vue Chart.js - 数据更改时图表未更新

[英]Vue Chart.js - Chart is not updating when data is changing

我正在使用 Vue.js 和 Chart.js 来绘制一些图表。 每次我调用 function generateChart()时,图表都不会自动更新。 当我检查 Vue Devtools 中的数据时,它们是正确的,但图表没有反映数据。 但是,当我调整 window 的大小时,图表确实会更新。

  • 我在做什么有什么问题?
  • 每次调用generateChart()时如何更新图表?

我觉得这将与objectarray更改检测警告有关,但我不确定该怎么做。

https://codepen.io/anon/pen/bWRVKB?editors=1010

<template>
    <el-dialog title="Chart" v-model="showGeneratedChart">
        <line-chart :chartData="dataChart"></line-chart>
    </el-dialog>
</template>

<script>
export default {
    data() {
        const self = this;
        return {
            dataChart: {
                labels: [],
                datasets: [
                    {
                        label: "label",
                        backgroundColor: "#FC2525",
                        data: [0, 1, 2, 3, 4],
                    },
                ],
            },
        };
    },
    methods: {
        generateChart() {
            this.dataChart["labels"] = [];
            this.dataChart["datasets"] = [];

            // ... compute datasets and formattedLabels

            this.dataChart["labels"] = formattedLabels;
            this.dataChart["datasets"] = datasets;
        },
    },
};
</script>         

LineChart.js

import { Line, mixins } from 'vue-chartjs'

export default Line.extend({
    mixins: [mixins.reactiveProp],
    props: ["options"],
    mounted () {
        this.renderChart(this.chartData, this.options)
    }
})

为图表数据使用计算属性。 而不是在 watch 上调用this.renderChart ,而是将其包装在一个方法中,并在 mount 和watch mounted重用该方法。

 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/vue-chartjs@2.5.7-rc3/dist/vue-chartjs.full.min.js"></script> </body> </html>

您还可以将选项设置为计算属性,如果选项不会发生太大变化,您可以设置默认道具。 https://v2.vuejs.org/v2/guide/components.html#Prop-Validation

这是一个工作的codepen https://codepen.io/azs06/pen/KmqyaN?editors=1010

我的解决方案是不使用 mixins 并使用监视道具。

watch: {
    chartData: function() {
        this.renderChart(this.chartData, this.options);
    }
  }

但是,这在我更改另一个组件中的 chartData 之前不起作用,如下所示:

this.chartData = {
            labels: [],
            datasets: []
};
this.chartData.labels = labels;
this.chartData.datasets = datasets;

如果我只是替换标签和数据集,手表就不会触发。

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)
}
}

添加自定义观察者以更新任何 vue 图表图形

我以前从未使用过 vue-chartjs,但看起来您唯一的问题是您忘记在折线图组件中明确接收 chartData 作为道具:

改变

export default Line.extend({
    mixins: [mixins.reactiveProp],
    props: ["options"],
    mounted () {
        this.renderChart(this.chartData, this.options)
    }
})

export default Line.extend({
    mixins: [mixins.reactiveProp],
    props: ["chartData", "options"],
    mounted () {
        this.renderChart(this.chartData, this.options)
    }
})

另外,在更改对象时要注意 vue 反应性问题,这不起作用:

this.dataChart['datasets'] = datasets;

你必须做这样的事情:

Vue.set(this.dataChart, 'datasets', datasets);

以便 Vue 检测对象的变化。

有关反应性的更多信息: https ://v2.vuejs.org/v2/guide/reactivity.html

有关图表反应性的更多信息:http: //vue-chartjs.org/#/home ?id=reactive-data

我只是在 nextTick 上重新渲染它而没有破坏并且工作正常。

(vue 3, vue3-chart-v2:0.8.2)

mounted () {
    this.renderLineChart();
},
methods: {
    renderLineChart() {
        this.renderChart(this.chartData, this.chartOptions);
    }
},
watch: {
    chartData () {
        this.$nextTick(() => {
            this.renderLineChart();
        })
    }
}

您的解决方案实际上几乎是正确的。 您不能直接修改图表数据集的子属性。 您必须设置this.datachart对象本身。 默认的 mixin mixins.reactiveProp会自动为组件的chartData属性添加一个观察者。 请参阅此处的文档。 这就是为什么如果没有进一步的代码就无法修改子属性,请参阅其他答案。

generateChart() {
    // If you want to clear all chart data (not necessary)
    this.dataChart = {}

    // Compute datasets and formattedLabels
    let formattedLabels = ...
    let datasets = ...

    this.dataChart = {
        labels: formattedLabels,
        datasets: datasets
    }
}

对于 Vue 3 组合 api,计算结果如下:

const chartData = computed(() => ({
  labels: [
    "Label 1",
    "Label 2"
  ],
  datasets: [
    { data: anyResponse.value.firstRowItems, label: 'Foo' },
    { data: anyResponse.value.secondRowItems, label: 'Bar' }
  ]
}));

在您的模板中:

<Line
  :chart-data="chartData"
/>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM