开发者问题收集

在 Vue 应用程序中尝试更新 Chart.js 中的图表数据时出现意外错误

2021-07-28
1475

我正在使用 Chart.js 3.5 和 Vue 3。 我成功地绘制了一个图表,并试图在 Vue 方法中触发数据更改。不幸的是,我遇到了以下问题:“未捕获的 TypeError:无法设置未定义的属性‘fullSize’”。

编辑 2:添加了一个遗漏的 }。代码现在应该可以运行了

MyChart.vue:

<template>
    <canvas id="chartEl" width="400" height="400" ref="chartEl"></canvas>
    <button @click="addData">Update Chart</button>
</template>

<script>
import Chart from 'chart.js/auto';

export default {
    name: "Raw",
    data() {
        return {
            chart: null
            
        }
    },
    methods: {
        createChart() {             

            this.chart= new Chart(this.$refs["chartEl"], {
                type: 'doughnut',
                data: {
                    labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
                    datasets: [
                        {
                        backgroundColor: [
                        '#41B883',
                        '#E46651',
                        '#00D8FF',
                        '#DD1B16'
                        ],
                        data: [100, 20, 80, 20]
                        }
                    ]
                },

                options: {
                    plugins: {}
                }
            })
        },


        addData() {
            const data = this.chart.data;
            if (data.datasets.length > 0) {
                data.labels.push('data #' + (data.labels.length + 1));

                for (var index = 0; index < data.datasets.length; ++index) {
                data.datasets[index].data.push(123);
                }
// Edit2: added missed }
            this.chart.update(); } // this line seems to cause the error}

        }
    },

    mounted () {

    this.createChart()
},

}
</script>

编辑 1:将以下内容添加到选项中可使图表成功更新,但错误仍然存​​在,动画不起作用。图表闪烁并显示最终(更新)状态。其他动画(例如隐藏/显示弧线)似乎不受影响

options: {
        
    responsive: true,

}

Edit3:添加“maintainAspectRatio:false”选项似乎再次停止图表更新(上述错误仍然存​​在)

通过调试器,'chart.esm.js'中的以下函数似乎被成功调用了几次,然后在最后一次调用时出错:

beforeUpdate(chart, _args, options) {
    const title = map.get(chart);  // this returns null, which will cause the next call to error with the above mentioned exception.
    layouts.configure(chart, title, options);
    title.options = options;
  },

//////////////////////
  configure(chart, item, options) {
    item.fullSize = options.fullSize;
    item.position = options.position;
    item.weight = options.weight;
  },
2个回答

这可能是一篇过时的帖子,但我刚刚花了几个小时来解决看似相同的问题。也许这会对您和/或未来遇到此问题的人有所帮助:

在将 Chart 对象分配为 Vue 组件的属性之前,请对其调用 Object.seal(...)

例如:

const chartObj = new Chart(...);
Object.seal(chartObj);
this.chart = chartObj;

这对我有用。Vue 积极地改变其权限范围内的对象的属性以增加反应性,据我所知,这会阻止 Chart 的内部识别这些对象以在需要时从其内部映射中检索其配置。 Object.seal 通过禁止对象添加任何新属性来防止这种情况。我指望 Chart 在初始化时添加了它需要的所有属性 - 如果我注意到任何奇怪的行为,我会更新这篇文章。

Alan Rowarth
2022-03-14

1 年后,Alan 的回答也帮助了我,但我的代码在调用 chart.destroy() 时失败了。

因此我搜索并找到了似乎是“vue 方式”来处理它: markRaw ,这里有一个使用选项 API 的示例:

import { markRaw } from 'vue'
// ...
export default {
  // ...
  beforeUnmount () {
    if (this.chart) {
      this.chart.destroy()
    }
  },
  methods: {
    createChart() {  
      const chart = new Chart(this.$refs["chartEl"], {
        // ... your chart data and options
      })
      this.chart = markRaw(chart)
    },
    addData() {
      // ... your update
      this.chart.update()
    },
  },
}

Nioc
2023-01-26