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

Blazor WASM删除表格行致子组件重渲染的解决方法问询

解决Blazor WASM删除表格行时子组件意外重渲染的问题

先确认@key是不是用对了

你说加了@key="@forecast.ForecastId"没效果,先检查这两点:

  • @key得加在循环渲染的那个元素/组件上,比如你循环<tr>就把@key放<tr>上,循环子组件就放子组件标签上,别加在外面的容器上。
  • 确保ForecastId是稳定不变的唯一值,别用索引或者会变的字段当key。

方法1:把WeatherForecast改成不可变对象

Blazor会对比组件参数的引用,如果你的Forecast对象是可变的(比如删除行时改了原对象的属性,或者直接修改列表里的元素),可能导致参数引用没变但内部状态变了,触发重渲染。

  • 改成不可变对象:每次要修改Forecast的属性时,返回一个新的实例,别直接改原对象。比如:
    var updatedForecast = forecast with { TemperatureC = newTemp };
    forecasts = forecasts.Select(f => f.ForecastId == updatedForecast.ForecastId ? updatedForecast : f).ToList();
    
    这样未被删除的项的对象引用不变,子组件就不会乱触发OnParametersSet。

方法2:重写SetParametersAsync手动控制参数更新

Blazor默认浅比较参数,你可以在子组件里自己判断参数有没有真的变化,再决定要不要执行昂贵操作:

  • 把子组件里的OnParametersSet逻辑移到SetParametersAsync里,手动对比新旧参数:
    public override async Task SetParametersAsync(ParameterView parameters)
    {
        var newForecast = parameters.GetValueOrDefault<WeatherForecast>("Forecast");
        // 只在ForecastId或者关键属性变化时才更新
        if (Forecast == null || newForecast.ForecastId != Forecast.ForecastId || newForecast.TemperatureC != Forecast.TemperatureC)
        {
            await base.SetParametersAsync(parameters);
            // 这里放你的昂贵API调用
            await LoadExpensiveData();
        }
        else
        {
            // 参数没变化,跳过更新
            parameters.SetParameterProperties(this);
        }
    }
    
    这样删除行时,只要子组件的参数没真的变,就不会重复调用API。

方法3:用缓存把API调用和组件渲染解耦

如果API调用只依赖ForecastId,可以搞个缓存服务,把每个ForecastId的结果存起来,子组件只在初始化时加载一次:

  • 先写个缓存服务:
    public class ForecastDataCache
    {
        private readonly Dictionary<int, ExpensiveData> _cache = new();
    
        public async Task<ExpensiveData> GetOrLoadData(int forecastId)
        {
            if (_cache.TryGetValue(forecastId, out var data))
                return data;
            // 执行API调用
            var newData = await FetchExpensiveDataFromApi(forecastId);
            _cache[forecastId] = newData;
            return newData;
        }
    }
    
    然后在子组件里注入这个服务,在OnInitializedAsync里加载数据(别用OnParametersSet),因为OnInitializedAsync只在组件创建时跑一次。就算组件被重渲染,直接从缓存取数据就行,不用再调用API。

方法4:更新列表时返回新实例

删除行的时候,别直接修改原列表,要创建新的列表实例:

  • 错误做法:forecasts.Remove(forecast);
  • 正确做法:
    forecasts = forecasts.Where(f => f.ForecastId != forecastToDelete.ForecastId).ToList();
    
    这样父组件的forecasts引用变了,Blazor能正确识别列表变化,配合@key就能复用现有子组件,不会重新创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 20:22:33