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里,手动对比新旧参数:
这样删除行时,只要子组件的参数没真的变,就不会重复调用API。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); } }
方法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
相关产品推荐
相关产品推荐

