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

Vue实现实时ApexChart:数据滚动与定时更新问题求助

Vue3 + ApexCharts 实时数据流图表实现问题

问题背景

尝试参考ApexCharts的实时折线图示例,但示例组件结构不实用且缺失部分方法,想要实现每1秒推送一个1秒数据块的实时图表,现有代码如下:

<template>
        <VueApexCharts
            type="line"
            height="350"
            width="100%"
            :options="chartOptions"
            :series="series"
            ref="chart"
        />
</template>

<script>
import { ref } from "vue";
import VueApexCharts from "vue3-apexcharts";
import { useStore } from "vuex";

export default {
    name: "ChartApex",
    components: { VueApexCharts },
    props: ["session"],
    setup(/* props */) {
        let store = useStore();
        let chartStream = undefined;
        let series = [
            {
                name: "data1",
                data: ref([]),
            },
            {
                name: "data2",
                data: [],
            },
        ];

        let chartOptions = {
            chart: {
                // id: "realtime",
                width: "100%",
                height: 350,
                type: "line",
                animations: {
                    enabled: true,
                    easing: "linear",
                    dynamicAnimation: {
                        speed: 1000,
                    },
                },
                toolbar: {
                    show: true,
                },
                zoom: {
                    enabled: true,
                },
            },
            dataLabels: {
                enabled: true,
            },
            stroke: {
                curve: "straight",
            },
            title: {
                text: "Chart",
                align: "left",
            },
            grid: {
                row: {
                    colors: ["#f3f3f3", "transparent"],
                    opacity: 0.5,
                },
            },
            xaxis: {
                type: "numeric",
                show: true,
                range: 3,
            },
            yaxis: {
                min: -32768,
                show: true,
                max: 32768,
            },
        };

        return {
            chartOptions,
            series,
            store,
            chartStream,
        };
    },

    watch: {
        "session.device.isDataStream"(newVal) {
            if (newVal) this.startStream();
            else this.endStream();
        },
    },
    methods: {
        startStream() {
            console.log("starting chart stream");
            this.chartStream = setInterval(() => {
                // Push data
                this.series[0].data.value.push(
                    ...this.store.state.session.samples[0].at(-1)
                );
            }, 1000);
        },
        endStream() {
            console.log("end chart srtrem");
            clearInterval(this.chartStream);
        },
    },
};
</script>

具体需求与疑问

  • X轴固定显示10秒的数据范围
  • 新增1秒数据块时,图表自动滚动X轴,始终保持显示10秒的数据
  • 目前从Vuex Store获取分块更新的数据,但图表数据堆叠且不滚动,希望每1秒推送一个数据块
  • 更倾向于直接绑定Store变量,但担心使用computed方法会降低性能

Store数据结构

store.state.samples[0]是包含多个1秒数据块的数组,格式如下:

// samples[0]
[
    // Chunk 1 of almost a second
    [
        [8.75, 0],
        [17.5, -1],
        [26.25, -2],
        [35, -3],...
        
    ],
    [ // Chunk 2 of almost a second.
        [958.6875, -12747],
        [962.375, -12808],
        [966.0625, -12789],...
    ]
]

解决方案

1. 修正数据推送逻辑,避免重复堆叠

当前定时器会重复推送最后一个数据块,需要新增索引记录已处理的块:
在setup函数中添加响应式变量:

let processedChunkIndex = ref(-1);

然后修改startStream方法:

startStream() {
    console.log("starting chart stream");
    this.chartStream = setInterval(() => {
        const latestChunks = this.store.state.session.samples[0];
        const newChunkIndex = latestChunks.length - 1;
        // 只推送未处理过的最新块
        if (newChunkIndex > processedChunkIndex.value) {
            this.series[0].data.value.push(...latestChunks[newChunkIndex]);
            processedChunkIndex.value = newChunkIndex;
            // 更新X轴范围实现滚动
            this.updateXAxisRange();
        }
    }, 1000);
}

2. 实现X轴固定10秒范围与自动滚动

首先修改chartOptions中的xaxis配置,移除固定range:

xaxis: {
    type: "numeric",
    show: true,
    min: undefined,
    max: undefined
},

然后新增updateXAxisRange方法:

updateXAxisRange() {
    const chartInstance = this.$refs.chart;
    if (!chartInstance) return;

    const data = this.series[0].data.value;
    if (data.length === 0) return;

    // 获取最新数据点的X值(时间)
    const latestX = data[data.length - 1][0];
    // 计算10秒范围的X轴区间
    const minX = latestX - 10;
    // 更新X轴范围并触发重绘
    chartInstance.updateOptions({
        xaxis: {
            min: minX,
            max: latestX
        }
    }, false, true);
}

3. 优化Store数据绑定与性能问题

  • 用watch监听Store数据变化替代定时器轮询,更高效:
    在setup函数中添加watch:
import { ref, watch } from "vue";

// ... 其他代码

watch(
    () => this.store.state.session.samples[0],
    (newChunks) => {
        if (!this.session.device.isDataStream) return;
        const newChunkIndex = newChunks.length - 1;
        if (newChunkIndex > processedChunkIndex.value) {
            this.series[0].data.value.push(...newChunks[newChunkIndex]);
            processedChunkIndex.value = newChunkIndex;
            this.updateXAxisRange();
        }
    },
    { deep: true }
);
  • 关于computed性能:如果只是映射Store数据到series,computed的开销极小,Vue会缓存计算结果,仅在依赖变化时重新计算。如果担心性能,用上述watch方式手动更新series即可,两者性能差异可以忽略。

4. 修复响应式问题

series中的data2未用ref包裹,改为响应式:

let series = [
    {
        name: "data1",
        data: ref([]),
    },
    {
        name: "data2",
        data: ref([]),
    },
];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:45:36