Blazor Server中Fusion Chart在Edge浏览器加载不稳定问题求助
Blazor Server中FusionChart在Edge浏览器加载不稳定的修复方案
问题根源
你的代码存在两个核心时序问题:
- 异步数据加载与组件渲染的竞态:
OnInitializedAsync中的数据库查询是异步操作,Blazor不会等待它完成就执行第一次渲染。因此当OnAfterRenderAsync(firstRender=true)触发时,dataSourceJson可能还未被赋值,导致渲染逻辑直接跳过。 - 仅依赖首次渲染触发图表渲染:即使后续数据加载完成并触发组件重新渲染,
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
相关产品推荐
相关产品推荐

