如何在vue中更新chart.js?

问题描述 投票:0回答:1

我创建了一个chart.js vue组件,它通过道具传递给它一些数据来渲染。现在,我希望能够在数据变化时调用图表上的update()方法。我的问题是,根据我的代码结构,我不能使用通常的chart.update()方法,因为我不能从它被创建的函数之外访问图表变量。我如何调整我的代码结构,使我能够调用图表上的更新方法?

此刻当数据发生变化时,我只是调用了初始渲染函数,这就会导致图表互相分层。当你改变数据然后悬停在图表上时,可以看到这一点。

Vue.component('chart', {
    template: '<canvas id="chart"></canvas>',
    props: {
        savings: Object,
    },
    watch: { 
        savings: {
            deep: true,
            handler() {
                console.log('Update Chart');
                this.createChart();
            }
        }
    },
    methods: {
        createChart() {
            new Chart(document.getElementById("chart"), {
                type: 'bar',
                data: {
                    datasets: [{
                        label: 'Bar Dataset',
                        data: [
                        	this.savings.annual[0], 
                            this.savings.annual[1], 
                            this.savings.annual[2], 
                            this.savings.annual[3],
                            this.savings.annual[4]
                        ]
                    }, {
                        label: 'Line Dataset',
                        data: [
                        	this.savings.cumulative[0], 
                            this.savings.cumulative[1], 
                            this.savings.cumulative[2], 
                            this.savings.cumulative[3],
                            this.savings.cumulative[4]
                        ],
                        type: 'line'
                    }],
                    labels: ['Year One', 'Year Two', 'Year Three', 'Year Four', 'Year Five']
                }
            });
        }
    },
    mounted() {
        this.createChart();
        console.log(this.totals);
    }
});

var app1 = new Vue({
    el: '#savings_calculator',
    data: {
        savings: {
        	annual: [123,345,234,234,523],
            cumulative: [234,523,234,423,100],
        }
    },
    methods: {
    	changeData() {
        	for(let i = 0; i < 5; i++) {
            	Vue.set(this.savings.annual, i, Math.floor((Math.random() * 1000) + 1));
                Vue.set(this.savings.cumulative, i, Math.floor((Math.random() * 1000) + 1));
            }
        	
        }
	}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="savings_calculator">
    <div class="input container">
        <button v-on:click="changeData">Change Data</button>
        <chart 
            v-bind:savings="savings"
        />
    </div>
</div>

我是在WordPress中工作的,我已经把chart.js库的代码复制到我的一个js文件中,这些文件都会被gulp压缩成一个文件。我之所以提到这一点,只是因为我看到有人使用import来包含库的例子。我确实下载了库到我的node_modules中,但我无法在我的js文件中导入。它给了我以下错误。

“Uncaught SyntaxError: Cannot use import statement outside a module” 
javascript vue.js chart.js
1个回答
1
投票

这个问题的发生主要是由于你在同一张图上绘制了多个图表。canvas 召见 createChart() 方法。你只需要调用 .destroy() 方法来销毁任何已创建的图表实例。这将清理任何存储在Chart.js中对图表对象的引用,以及任何由Chart.js附加的相关事件监听器。在画布被重新用于新的图表之前,必须调用这个方法。

因此,简单地添加一个新的数据选项来存储当前的图表实例,如:。

data(){
  return{
    chart: null
  }
},

然后像这样存储图表实例。

 createChart() {
    this.chart = new Chart(document.getElementById("chart"), {
    ...

然后在里面 watch 呼叫前 this.createChart(); 使用。

  this.chart.destroy();
  this.createChart();

工作示范:

Vue.component('chart', {
  template: '<canvas id="chart"></canvas>',
  props: {
    savings: Object,
  },
  data(){
    return{
      chart: null
    }
  },
  watch: {
    savings: {
      deep: true,
      handler() {
        console.clear();
        console.log('Update Chart');
        this.chart.destroy();
        this.createChart();
      }
    }
  },
  methods: {
    createChart() {
      this.chart = new Chart(document.getElementById("chart"), {
        type: 'bar',
        data: {
          datasets: [{
            label: 'Bar Dataset',
            data: [...this.savings.annual]
          }, {
            label: 'Line Dataset',
            data: [...this.savings.cumulative],
            type: 'line'
          }],
          labels: ['Year One', 'Year Two', 'Year Three', 'Year Four', 'Year Five']
        }
      });
    }
  },
  mounted() {
    this.createChart();
    //console.log(this.totals);
  }
});

var app1 = new Vue({
  el: '#savings_calculator',
  data: {
    savings: {
      annual: [123, 345, 234, 234, 523],
      cumulative: [234, 523, 234, 423, 100],
    }
  },
  methods: {
    changeData() {
      for (let i = 0; i < 5; i++) {
        Vue.set(this.savings.annual, i, Math.floor((Math.random() * 1000) + 1));
        Vue.set(this.savings.cumulative, i, Math.floor((Math.random() * 1000) + 1));
      }

    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="savings_calculator">
  <div class="input container">
    <button v-on:click="changeData">Change Data</button>
    <chart v-bind:savings="savings" />
  </div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.