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

Blazor循环动态添加Razor图表组件触发lineChart空引用报错

问题根因

空引用的核心原因是Blazor组件@ref引用的赋值时机与数据加载时机不匹配:

  • Blazor中通过@ref捕获的子组件实例,仅会在子组件完成首次渲染挂载后才会被赋值
  • 静态写死组件时,页面首次渲染会按顺序完成所有子组件挂载,lineChart引用正常赋值,后续操作无异常
  • foreach动态渲染、或条件渲染新增的组件,若在子组件挂载完成前就调用DataSetToChartSeries方法,此时lineChart仍为默认null,就会抛出空引用异常
  • 现有代码大概率是在OnParametersSetAsync等渲染前生命周期中直接调用了数据绑定逻辑,动态生成的组件触发参数设置时,内部的LineChart子组件还未完成渲染,引用自然为空。
修复步骤

1. 给动态列表项增加唯一Key

Blazor默认会复用列表渲染的组件实例,易导致引用赋值错乱,给foreach内的每个组件配置唯一@key,保证实例独立渲染:

@foreach (string graphSelector in datasets)
{
     <ChartComponent 
        @key="graphSelector"
        ViewHeight=50 
        ViewWidth=80 
        ColorScheme="Classic20" 
        Multiple=true 
        Items=@(items.Where(p => p.CounterInstance == graphSelector).ToList())>
    </ChartComponent>
}

2. 调整数据加载时机,仅在组件挂载完成后操作图表实例

重写ChartComponent的OnAfterRenderAsync生命周期方法,该方法触发时子组件已经完成渲染,@ref引用已完成赋值:

private bool _isFirstRender = true;
private bool _needRefreshData = false;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        _isFirstRender = false;
        if (_needRefreshData)
        {
            await DataSetToChartSeries();
            _needRefreshData = false;
        }
    }
}

3. 兼容参数动态更新场景

如果组件挂载后Items参数会动态变更,在参数变更生命周期中增加引用判断,未挂载时标记待刷新,已挂载时直接加载数据:

protected override async Task OnParametersSetAsync()
{
    if (_isFirstRender)
    {
        _needRefreshData = true;
        return;
    }
    await DataSetToChartSeries();
}

4. 增加空值防护

在DataSetToChartSeries入口增加null判断,规避极端时序问题:

private async Task DataSetToChartSeries()
{
    if (lineChart == null) return;
    
    // 原有业务逻辑保留
    string[] dateLabels = Items.Select(x => x.TimeRun.ToString("yyyy-MM-dd hh:mm")).Distinct().ToArray();
    await lineChart.Clear();
    await lineChart.AddLabels(dateLabels);
    if (Multiple)
    {
        List<string> graphDatasets = Items.Select(p => p.CounterInstance).Distinct().ToList();
        foreach (string graphSelector in graphDatasets)
        {
            List<QueryResult> currentDataSet = Items.Where(p => p.CounterInstance == graphSelector).ToList();
            await lineChart.AddDataSet(GetLineChartDataset(currentDataSet));
        }
    }
    else
    {
        await lineChart.AddDataSet(GetLineChartDataset(Items));
    }
    await lineChart.Update();
}

注意:不要在OnInitialized、OnParametersSet这类渲染执行前的生命周期方法中直接操作@ref捕获的子组件,这两个阶段子组件尚未实例化挂载,引用必然为null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:24:15