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

时间:2017-05-02 00:26:27

标签: javascript charts vue.js

我使用Vue.js和Chart.js绘制一些图表。 每次调用函数generateChart()时,图表都不会自动更新。当我检查VueDevTools中的数据时,它们是正确的,但图表并不代表那些。

有趣的事实:当我调整窗口大小时,图表正在更新。

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

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

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

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

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

6 个答案:

答案 0 :(得分:22)

对图表数据使用计算属性。而不是在监视中调用this.renderChart将其包装在方法中,并在mountedwatch中重用该方法。

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://vuejs.org/v2/guide/components.html#Prop-Validation

这是一个有效的代码集https://codepen.io/azs06/pen/KmqyaN?editors=1010

答案 1 :(得分:2)

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图表图表

答案 2 :(得分:1)

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

更改

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

this.dataChart['datasets'] = datasets;

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

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

你必须做这样的事情:

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-Light.ttf') format('truetype');
font-weight: 300;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-LightItalic.ttf') format('truetype');
font-weight: 300;
font-style: italic;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-Italic.ttf') format('truetype');
font-style: italic;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-SemiBold.ttf') format('truetype');
font-weight: 600;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-SemiBoldItalic.ttf') format('truetype');
font-weight: 600;
font-style: italic;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-Bold.ttf') format('truetype');
font-weight: 700;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-BoldItalic.ttf') format('truetype');
font-weight: 700;
font-style: italic;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-ExtraBold.ttf') format('truetype');
font-weight: 800;
}

@font-face {
    font-family: 'Raleway55';
    src: url('/wp-content/uploads/font-organizer/Raleway-ExtraBoldItalic.ttf') format('truetype');
font-weight: 800;
font-style: italic;
}

body { font-family: 'Raleway55'!important; font-weight:normal!important;  }
h1 { font-family: 'Raleway55'!important; font-weight:normal!important;  }
h2 { font-family: 'Raleway55'!important; font-weight:normal!important;  }
h3 { font-family: 'Raleway55'!important; font-weight:normal!important;  }
h4 { font-family: 'Raleway55'!important; font-weight:normal!important;  }
h5 { font-family: 'Raleway55'!important; font-weight:normal!important;  }
h6 { font-family: 'Raleway55'!important; font-weight:normal!important;  }
p { font-family: 'Raleway55'!important; font-weight:normal!important;  }
q { font-family: 'Raleway55'!important; font-weight:normal!important;  }
li { font-family: 'Raleway55'!important; font-weight:normal!important;  }
a { font-family: 'Raleway55'!important; font-weight:normal!important;  } <code>

按顺序Vue检测对象的变化。

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

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

答案 3 :(得分:1)

我的解决方案是不使用混合器,而对道具使用手表。

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

但是,直到我在另一个组件中更改chartData时,这才起作用:

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

如果我只更换标签和数据集,手表将不会被开除。

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

我只是在 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();
        })
    }
}