首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Vue js中试图更新图表时的最大调用堆栈错误

在Vue js中试图更新图表时的最大调用堆栈错误
EN

Stack Overflow用户
提问于 2021-07-31 13:03:23
回答 2查看 2.2K关注 0票数 2

我有一个用Chart.js 3.5库绘制的线状图。图表呈现正确,响应性强,所有动画都正常工作。我试图从父组件触发数据更新,并触发图表更新。当调用chart.update()时,会抛出一个异常:"Uncaught (承诺) RangeError:超过最大调用堆栈大小“,我使用的是Vue 3和Chart.js 3.5

Edit1:这是一个复制错误的沙盒

其逻辑如下:

  1. 图表数据通过道具从父传递到子。默认情况下,shouldUpdate支柱是假的。
  2. 在使用“createChart”方法挂载子组件和父级数据时绘制图表
  3. 一个观察孩子的人在看“shouldUpdate”道具的变化。
  4. 在父组件内部单击按钮时,“shouldUpdate”设置为True,从而触发子组件上的观察者。
  5. 子程序更改图表数据,更新图表,并将“shouldUpdate”支柱重置为False。

预期结果:

  1. 图表是用父组件的数据呈现的。
  2. 图表根据从父级传递的选项显示响应/动画。
  3. 从父级收到触发器时更新的图表

实际结果:

  1. 图表是用父组件的数据呈现的。
  2. 图表根据从父级传递的选项显示响应/动画。
  3. 图表更新失败,“最大调用堆栈大小超过”错误。

父元素: Line.vue

代码语言:javascript
复制
<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>

子组件: Raw.vue

代码语言:javascript
复制
<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>

错误跟踪:

代码语言:javascript
复制
[Vue warn]: Unhandled error during execution of watcher callback 
  at <Raw type="line" options= {} data= {labels: Array(7), datasets: Array(2)}  ... > 
  at <App> 
代码语言:javascript
复制
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> 
代码语言:javascript
复制
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)

沙盒来复制错误。

EN

回答 2

Stack Overflow用户

发布于 2021-08-01 11:13:03

添加Petru解决方案,使图表非反应性,您也可以使用shallowRef

代码语言:javascript
复制
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,
        })
      );
    },
  },
票数 7
EN

Stack Overflow用户

发布于 2021-07-31 23:09:27

我找到了一个适用于我的特殊情况的解决办法,但可能并不是每个人都很理想。

解决方法是使图表对象非反应性,以便Vue不跟踪对其的更改,方法是将其移出组件“data”的“返回”语句。图表对象仍然在组件中的任何地方都可用,所有功能(响应性、动画等)都按预期工作,但Vue没有跟踪其他任何地方,因此,如果您试图跨组件传递图表对象,或者将其与Vuex一起使用,可能会导致问题。

守则如下:

不起作用:

代码语言:javascript
复制
<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,
        };
    },
....
}

工作:

代码语言:javascript
复制
<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,
        };
    },
....
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68602389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档