【问题标题】:How to update chart.js in vue如何在 vue 中更新 chart.js
【发布时间】:2020-05-06 11:00:29
【问题描述】:

我创建了一个 chart.js vue 组件,它使用一些通过 props 传递给它的数据进行渲染。现在我希望能够在数据发生变化时调用图表上的 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 中工作,我通过将代码复制到我的一个 js 文件中包含了 chart.js 库,所有这些文件都被 gulp 压缩并压缩到一个文件中。我之所以提到这一点,是因为我见过人们使用 import 来包含库的示例。我确实将库下载到我的 node_modules 中,但我无法让导入在我的 js 文件中工作。它给了我以下错误:

“Uncaught SyntaxError: Cannot use import statement outside a module” 

【问题讨论】:

    标签: javascript vue.js chart.js


    【解决方案1】:

    这个问题主要是因为您在调用createChart() 方法时在同一个canvas 上绘制多个图表。您只需要调用.destroy() 方法来销毁任何已创建的图表实例。这将清除存储在 Chart.js 中的图表对象的所有引用,以及 Chart.js 附加的任何关联事件侦听器。这必须在画布重新用于新图表之前调用。

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

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

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

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

    在调用this.createChart();之前在watch内部使用:

      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>

    【讨论】:

    • 这很好用,谢谢。我确实必须为我的项目更改以下语法。 data() { return{chart: null } }data: { chart: null }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2020-02-07
    • 2020-11-12
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    相关资源
    最近更新 更多