Pet*_*nas 10 javascript vue.js chart.js vuejs3
我有一个使用 Chart.js 3.5 库绘制的折线图。图表渲染正确,响应灵敏,并且所有动画均有效。我正在尝试从父组件触发数据更新,并触发图表更新。调用时chart.update(),会抛出异常:“未捕获(在承诺中)RangeError:超出最大调用堆栈大小”我正在使用 Vue 3 和 Chart.js 3.5
Edit1:这是一个沙箱来复制错误。
逻辑如下:
预期结果:
实际结果:
父元素:Line.vue
<template>
<raw
:type="type"
:options="options"
:data="chartData"
:shouldUpdate="shouldUpdate"
:resetUpdate="resetUpdate"
/>
<button @click="updateData"></button>
</template>
<script>
import Raw from "./Raw.vue";
export default {
name: "App",
components: {
Raw,
},
computed: {
chartData: function () {
return this.data;
},
},
methods: {
updateData() {
this.shouldUpdate = true;
},
resetUpdate() {
this.shouldUpdate = false;
},
},
data() {
return {
type: "line",
shouldUpdate: false,
options: {
responsive: true,
animation: true,
maintainAspectRatio: false,
},
data: {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "June", "July"],
datasets: [
{
label: "My line Dataset",
data: [65, 59, 80, 81, 56, 55, 40],
fill: false,
borderColor: "rgb(75, 192, 192)",
tension: 0.1,
},
{
label: "My second line Dataset",
data: [100, 79, 8, 80, 90, 55, 60],
fill: false,
borderColor: "rgb(75, 19, 192)",
tension: 0.1,
},
],
},
};
},
};
</script>
Run Code Online (Sandbox Code Playgroud)
子组件:Raw.vue
<template>
<canvas />
</template>
<script>
import Chart from "chart.js/auto";
export default {
name: "Raw",
props: ["type", "data", "options", "shouldUpdate", "resetUpdate"],
data() {
return {
chart: null,
localData: null,
};
},
computed: {
parentEl: function () {
const size = Math.min(this.$parent.width, this.$parent.height);
return { height: size, width: size };
},
},
watch: {
shouldUpdate: function (val) {
console.log(val);
if (val) {
console.log("updateTriggered");
console.log(this.chart.data.datasets[0].data[5])
this.chart.data.datasets[0].data[5] = Math.round(Math.random() * 100)
console.log(this.chart.data.datasets[0].data[5]) // check if data changed
this.chart.update(); // this seems to cause the error
}
},
},
methods: {
createChart() {
this.localData = this.data;
this.chart = new Chart(this.$el, {
type: this.type,
data: this.localData,
options: this.options,
});
},
},
mounted() {
this.createChart();
},
};
</script>
<style scoped>
</style>
Run Code Online (Sandbox Code Playgroud)
错误回溯:
[Vue warn]: Unhandled error during execution of watcher callback
at <Raw type="line" options= {} data= {labels: Array(7), datasets: Array(2)} ... >
at <App>
Run Code Online (Sandbox Code Playgroud)
runtime-core.esm-bundler.js?5c40:38 [Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next
at <Raw type="line" options= {} data= {labels: Array(7), datasets: Array(2)} ... >
at <App>
Run Code Online (Sandbox Code Playgroud)
Uncaught (in promise) RangeError: Maximum call stack size exceeded
at _resolveWithPrefixes (helpers.segment.js?dd3d:1797)
at eval (helpers.segment.js?dd3d:1605)
at _cached (helpers.segment.js?dd3d:1687)
at Object.get (helpers.segment.js?dd3d:1604)
at _resolveWithContext (helpers.segment.js?dd3d:1695)
at eval (helpers.segment.js?dd3d:1647)
at _cached (helpers.segment.js?dd3d:1687)
at Object.get (helpers.segment.js?dd3d:1646)
at toRaw (reactivity.esm-bundler.js?a1e9:743)
at toRaw (reactivity.esm-bundler.js?a1e9:743)
Run Code Online (Sandbox Code Playgroud)
沙箱来复制错误。
Lee*_*lee 17
添加 Petru Tanas 解决方法以使图表不反应,您也可以使用shallowRef
import { shallowRef } from 'vue';
data() {
return {
chart: null,
localData: null,
};
},
methods: {
createChart() {
this.localData = this.data;
this.chart = shallowRef(
new Chart(this.$el, {
type: this.type,
data: this.localData,
options: this.options,
})
);
},
},
Run Code Online (Sandbox Code Playgroud)
我找到了一种适用于我的特定情况的解决方法,但可能并不适合所有人。
解决方法是通过将图表对象移出组件“data”的“return”语句,使图表对象成为非响应式的,以便 Vue 不会跟踪其变化。图表对象仍然在组件内的任何地方可用,并且所有功能(响应式、动画等)都按预期工作,但 Vue 不会在其他任何地方跟踪它,因此如果您尝试跨组件传递它,或者使用与 Vuex 一起使用
代码如下:
不起作用:
<template>
<canvas />
</template>
<script>
import Chart from "chart.js/auto";
export default {
name: "Raw",
props: ["type", "data", "options", "shouldUpdate", "resetUpdate"],
data() {
return {
chart: null, // this line will change
localData: null,
};
},
....
}
Run Code Online (Sandbox Code Playgroud)
在职的:
<template>
<canvas />
</template>
<script>
import Chart from "chart.js/auto";
export default {
name: "Raw",
props: ["type", "data", "options", "shouldUpdate", "resetUpdate"],
data() {
this.chart = null // this line changed
return {
localData: null,
};
},
....
}
Run Code Online (Sandbox Code Playgroud)