You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue 3修改带响应式配置的ApexCharts选项触发过多递归错误

Vue 3 + ApexCharts 响应式配置引发递归溢出问题解决

问题现象

在Vue 3.2.13配合ApexCharts 3.53.0时,只要图表配置中包含responsive数组:

  • 无论是直接替换整个optionsData对象,还是调用$refs.myApex.updateOptions()修改配置,都会触发too much recursion递归错误,图表直接消失
  • 直接修改this.optionsData.colors这类属性无任何响应
  • 移除responsive配置后,所有操作恢复正常

错误栈指向Vue响应式模块与ApexCharts内部代码的递归调用:

Uncaught runtime errors:
ERROR
too much recursion
ownKeys@webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:1040:5
value@webpack-internal:///./node_modules/apexcharts/dist/apexcharts.common.js:5:7558
value@webpack-internal:///./node_modules/apexcharts/dist/apexcharts.common.js:5:7592
...(重复递归调用)

触发场景代码

模板代码:

<apexchart ref="myApex" class="chart" height="100%" type="line" :options="optionsData" :series="seriesData"></apexchart>

脚本代码:

methods: {
    updateOptionsData() {
        this.optionsData = {
            chart: {
                id: this.chartId,
                height: '100%',
            },
            responsive: [ 
                {
                    breakpoint: 768,
                    options: {
                        tooltip: {
                            enabled: false,
                        },
                    },
                },
            ],
        };
    },
},
mounted() {
    this.updateOptionsData();
    setTimeout(
        () => {
            console.log(237);
            this.optionsData = {
                ...this.optionsData,
                colors: ['#000000', '#666666', '#AAAAAA', '#FFFFFF'],
            };
            console.log(238);
        },
        5000,
    );
},

调用updateOptions同样触发错误:

this.$refs.myApex.updateOptions({
    colors: ['#000000', '#666666', '#AAAAAA', '#FFFFFF'],
});

原因分析

Vue 3的响应式系统会对传入的配置对象进行深度代理,而ApexCharts在处理responsive配置时会深度遍历、修改该对象,二者的属性拦截逻辑叠加,引发无限递归调用。

解决方案

方案1:冻结响应式配置对象

用Object.freeze()冻结responsive数组或内部对象,让Vue跳过对其的响应式代理:

updateOptionsData() {
    this.optionsData = {
        chart: {
            id: this.chartId,
            height: '100%',
        },
        responsive: Object.freeze([ 
            {
                breakpoint: 768,
                options: Object.freeze({
                    tooltip: {
                        enabled: false,
                    },
                }),
            },
        ]),
    };
}

方案2:标记配置为非响应式

使用Vue的markRaw()方法,将整个配置对象标记为永远不转为响应式,避免响应式系统干扰第三方库的内部处理:

import { markRaw } from 'vue';

// ...

updateOptionsData() {
    this.optionsData = markRaw({
        chart: {
            id: this.chartId,
            height: '100%',
        },
        responsive: [ 
            {
                breakpoint: 768,
                options: {
                    tooltip: {
                        enabled: false,
                    },
                },
            },
        ],
    });
}

// 更新颜色时同样用markRaw包裹
setTimeout(() => {
    this.optionsData = markRaw({
        ...this.optionsData,
        colors: ['#000000', '#666666', '#AAAAAA', '#FFFFFF'],
    });
}, 5000);

方案3:升级ApexCharts版本

该递归问题在ApexCharts 3.55.0及以上版本中已被官方修复,直接升级依赖即可解决。

补充说明

直接修改this.optionsData.colors无效果,是因为Vue响应式系统无法检测到对象新增属性的变化(原配置对象初始没有colors属性),必须通过替换整个对象的方式触发响应式更新。

内容的提问来源于stack exchange,提问作者SimonMayer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 15:07:33