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

Blazor Server中Fusion Chart在Edge浏览器加载不稳定问题求助

Blazor Server中FusionChart在Edge浏览器加载不稳定的修复方案

问题根源

你的代码存在两个核心时序问题:

  1. 异步数据加载与组件渲染的竞态:OnInitializedAsync中的数据库查询是异步操作,Blazor不会等待它完成就执行第一次渲染。因此当OnAfterRenderAsync(firstRender=true)触发时,dataSourceJson可能还未被赋值,导致渲染逻辑直接跳过。
  2. 仅依赖首次渲染触发图表渲染:即使后续数据加载完成并触发组件重新渲染,firstRender只会为true一次,后续的OnAfterRenderAsync不会再执行渲染逻辑。

此外,Edge浏览器的渲染机制可能对未完全加载的JS库更敏感,导致偶尔出现图表闪显后消失的情况。

修复步骤与代码修改

1. 组件端代码调整

添加DOM容器引用,修改生命周期逻辑,确保数据就绪后触发图表渲染:

<!-- 给图表容器添加引用 -->
<div @ref="chartContainer" style="width:100%;height:400px;"></div>

@code {
    private ElementReference chartContainer;
    private string? dataSourceJson;
    private bool isChartInitialized;

    protected override async Task OnInitializedAsync()
    {
        var eventData = await FetchEventDataFromDatabase();
        PrepareChartData(eventData);
        // 手动触发状态变更,确保组件重新渲染以执行后续渲染逻辑
        StateHasChanged();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        // 仅当数据就绪且图表未初始化时执行渲染
        if (!string.IsNullOrEmpty(dataSourceJson) && !isChartInitialized)
        {
            // 确保FusionChart JS库已加载(根据实际加载方式调整)
            await EnsureFusionChartLoaded();
            // 传入DOM容器引用,确保渲染目标存在
            await JSRuntime.InvokeVoidAsync("renderFusionChart", chartContainer, dataSourceJson);
            isChartInitialized = true;
        }
        // 若数据更新,重新加载图表数据
        else if (!string.IsNullOrEmpty(dataSourceJson) && isChartInitialized)
        {
            await JSRuntime.InvokeVoidAsync("updateFusionChart", chartContainer, dataSourceJson);
        }
    }

    // 确保FusionChart库加载完成的辅助方法
    private async Task EnsureFusionChartLoaded()
    {
        bool isLoaded = await JSRuntime.InvokeAsync<bool>("checkFusionChartLoaded");
        if (!isLoaded)
        {
            await JSRuntime.InvokeVoidAsync("loadFusionChartScripts");
        }
    }

    // 以下为原有代码,无需修改
    private async Task<List<DailyAlarmData>> FetchEventDataFromDatabase()
    {
        return await context.AlarmData
            .Where(a => a.EventTime.HasValue)
            .GroupBy(a => a.EventTime.Value.Date)
            .Select(group => new DailyAlarmData
                {
                    Date = group.Key,
                    Count = group.Count()
                })
            .ToListAsync();
    }

    private void PrepareChartData(List<DailyAlarmData> eventData)
    {
        var chartData = new
        {
            chart = new
            {
                caption = "Daily Event Count",
                subCaption = "For the current month",
                xAxisName = "Day",
                yAxisName = "Number of Events",
                theme = "fusion"
            },
            data = eventData.Select(e => new { label = e.Date.ToString("yyyy-MM-dd"), value = e.Count }).ToList()
        };

        dataSourceJson = System.Text.Json.JsonSerializer.Serialize(chartData);
    }

    public class DailyAlarmData
    {
        public DateTime Date { get; set; }
        public int Count { get; set; }
    }
}

2. 配套JavaScript代码(wwwroot/scripts/fusion-chart-utils.js)

添加JS工具函数,确保库加载状态并处理图表渲染:

// 检查FusionChart是否已加载
window.checkFusionChartLoaded = () => {
    return typeof FusionCharts !== 'undefined';
};

// 动态加载FusionChart脚本(若未提前在Layout中加载)
window.loadFusionChartScripts = async () => {
    if (!window.FusionCharts) {
        // 加载核心库
        await loadScript('https://cdn.fusioncharts.com/fusioncharts/latest/fusioncharts.js');
        // 加载主题
        await loadScript('https://cdn.fusioncharts.com/fusioncharts/latest/themes/fusioncharts.theme.fusion.js');
    }
};

// 辅助加载脚本的函数
function loadScript(url) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = url;
        script.async = false;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
    });
}

// 渲染图表
window.renderFusionChart = (container, dataSource) => {
    FusionCharts.ready(() => {
        new FusionCharts({
            type: 'column2d', // 根据你的需求修改图表类型
            renderAt: container,
            width: '100%',
            height: '100%',
            dataFormat: 'json',
            dataSource: JSON.parse(dataSource)
        }).render();
    });
};

// 更新图表数据
window.updateFusionChart = (container, dataSource) => {
    const chart = FusionCharts(container.id);
    if (chart) {
        chart.setJSONData(JSON.parse(dataSource));
    }
};

3. 可选优化:提前在Layout中加载脚本

如果希望避免动态加载的延迟,可直接在_Layout.cshtml的<head>或<body>末尾添加FusionChart脚本引用:

<script src="https://cdn.fusioncharts.com/fusioncharts/latest/fusioncharts.js"></script>
<script src="https://cdn.fusioncharts.com/fusioncharts/latest/themes/fusioncharts.theme.fusion.js"></script>
<script src="~/scripts/fusion-chart-utils.js"></script>

关键优化点说明

  • 消除竞态条件:通过StateHasChanged()手动触发重新渲染,确保数据就绪后执行图表渲染逻辑。
  • DOM元素确保:直接传入图表容器的ElementReference,避免因DOM未加载完成导致的渲染失败。
  • JS库加载校验:确保FusionChart库完全加载后再执行渲染,适配Edge浏览器的严格渲染机制。
  • 支持数据更新:添加图表数据更新逻辑,后续数据变更时可直接刷新图表内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:00:34