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

如何基于SvelteKit Store的数据刷新/更新Apache ECharts图表?

问题描述

尝试在SvelteKit中基于Store数据刷新Apache ECharts图表,点击按钮传入简单数据对象也无效。图表可通过onMount正常绘制,但响应式刷新和按钮触发重绘均失败。

组件代码(diagram.svelte)

<script>
    import * as echarts from "echarts";
    import { onMount } from "svelte";
    import { dummyStoreObj } from "$lib/stores.js";

    export let data;

    let myChart;
    let chartDom;
    let myChart_option;

    function drawChart() {
        chartDom = document.getElementById("chartDiv");
        myChart = echarts.init(chartDom);

        myChart_option = {
            dataset: {
                dimensions: ["start_time", "bucket", "folder", "name"],
                source: data,
            },
            xAxis: {
                type: "time",
                name: "date/time",
                nameLocation: "middle",
                splitLine: { show: true },
            },
            yAxis: {
                type: "category",
                name: "# folder",
                nameGap: "1",
                splitLine: { show: true },
            },
            series: [
                {
                    type: "scatter",
                    encode: {
                        x: "start_time",
                        y: "folder",
                    },
                },
            ],
        };

        myChart_option && myChart.setOption(myChart_option);
    }

    const reDrawChart = async () => {
        console.log("Redraw called");

        myChart_option.source = dummyStoreObj.data;
        myChart.setOption(myChart_option);
    };

    onMount(async () => {
        drawChart();
    });
</script>

<div>
    <button on:click={reDrawChart}>Redraw Chart</button>
</div>
<div id="chartDiv" />

<style>
    #chartDiv {
        height: 200px;
        width: auto;
        border: 1px solid #141413;
    }
</style>

Store代码(stores.js)

const dummyStoreObj = {
    data: [{
        start_time: '2023-01-31T07:45:11.286491+01:00',
        bucket: 'bucketName',
        folder: 'folderName',
        filename: 'filename.txt'
    }]
};
export const storeData = writable(
    JSON.parse(
        dummyStoreObj || '',
    ));
问题原因
  1. Store使用错误:组件导入的是静态对象dummyStoreObj,未使用实际的writable store;JSON.parse(dummyStoreObj || '')会报错,因为dummyStoreObj是对象而非JSON字符串。
  2. 图表更新逻辑错误:reDrawChart中直接修改myChart_option.source,但ECharts的数据源嵌套在dataset下,修改顶层source无法被正确识别。
  3. 未监听Store变化:组件未订阅Store的更新事件,Store数据变更时无法触发图表重绘。
修复方案

1. 修正Store定义(stores.js)

import { writable } from 'svelte/store';

const initialData = [{
    start_time: '2023-01-31T07:45:11.286491+01:00',
    bucket: 'bucketName',
    folder: 'folderName',
    filename: 'filename.txt'
}];

export const chartDataStore = writable(initialData);

2. 修正组件逻辑(diagram.svelte)

<script>
    import * as echarts from "echarts";
    import { onMount, onDestroy } from "svelte";
    import { chartDataStore } from "$lib/stores.js";

    export let data;

    let myChart;
    let chartDom;
    let unsubscribe;

    // 通用图表更新函数
    function updateChart(chartData) {
        if (!myChart) return;
        
        const option = {
            dataset: {
                dimensions: ["start_time", "bucket", "folder", "filename"],
                source: chartData,
            },
            xAxis: {
                type: "time",
                name: "date/time",
                nameLocation: "middle",
                splitLine: { show: true },
            },
            yAxis: {
                type: "category",
                name: "# folder",
                nameGap: "1",
                splitLine: { show: true },
            },
            series: [
                {
                    type: "scatter",
                    encode: {
                        x: "start_time",
                        y: "folder",
                    },
                },
            ],
        };

        // 强制替换旧配置,确保数据完全更新
        myChart.setOption(option, true);
    }

    onMount(() => {
        chartDom = document.getElementById("chartDiv");
        myChart = echarts.init(chartDom);
        // 初始渲染
        updateChart(data);

        // 订阅Store变化,自动更新图表
        unsubscribe = chartDataStore.subscribe(newData => {
            updateChart(newData);
        });

        // 窗口大小变化时自适应
        const handleResize = () => myChart?.resize();
        window.addEventListener('resize', handleResize);

        return () => {
            window.removeEventListener('resize', handleResize);
            myChart?.dispose();
        };
    });

    // 按钮触发:更新Store数据,自动触发图表重绘
    const reDrawChart = () => {
        chartDataStore.update(current => [
            ...current,
            {
                start_time: '2023-02-01T08:30:00+01:00',
                bucket: 'newBucket',
                folder: 'newFolder',
                filename: 'newFile.txt'
            }
        ]);
    };

    onDestroy(() => {
        unsubscribe?.();
        myChart?.dispose();
    });
</script>

<div>
    <button on:click={reDrawChart}>Redraw Chart</button>
</div>
<div id="chartDiv" />

<style>
    #chartDiv {
        height: 200px;
        width: auto;
        border: 1px solid #141413;
    }
</style>

关键修复点

  • 正确使用Store:导入并订阅chartDataStore,数据变化时自动触发图表更新。
  • 数据源字段匹配:修正dimensions中的字段名,与数据源的filename保持一致。
  • 强制更新配置:调用setOption时传入第二个参数true,强制替换旧配置,确保数据完全生效。
  • 资源清理:组件销毁时取消Store订阅、销毁ECharts实例、移除窗口resize监听,避免内存泄漏。

内容的提问来源于stack exchange,提问作者George.Ef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:05:45