Blazor WebAssembly中jQuery修改表格后同步组件数据
解决Blazor WebAssembly中jQuery Numpad修改单元格后同步数据到WeatherForecast集合的问题
要实现DOM修改后同步到Blazor组件的数据源,核心是通过JS Interop将JS侧的修改事件传递给.NET组件,更新组件内的WeatherForecast集合,触发Blazor自动重新渲染,确保页面与数据一致。以下是具体实现步骤:
1. 给目标单元格添加数据源标识
渲染表格时,为带有odd类的单元格绑定data-*属性,存储对应WeatherForecast项的唯一标识(如ID)和要修改的属性名,让JS能定位到组件内的目标数据。
<table class="table"> @foreach (var forecast in forecasts) { <tr> <!-- 给奇数行的温度单元格添加odd类和数据标识 --> <td class="@(forecast.Id % 2 == 1 ? "odd" : "")" data-forecast-id="@forecast.Id" data-target-property="TemperatureC"> @forecast.TemperatureC </td> <td>@forecast.Summary</td> <!-- 其他列 --> </tr> } </table>
2. 配置jQuery Numpad的回调函数
封装Numpad初始化逻辑,在值修改完成的onClose回调中,通过window.DotNet.invokeMethodAsync将新值、数据ID、目标属性名传递给Blazor组件。
// 封装初始化函数,供Blazor组件渲染完成后调用 window.initNumpad = function() { $('.odd').numpad({ // 配置Numpad的其他参数(如格式、按钮等) decimalPlaces: 0, onClose: function(newValue, numpadInstance) { const $cell = numpadInstance.$el; // 从data属性获取标识信息 const forecastId = parseInt($cell.data('forecast-id')); const targetProperty = $cell.data('target-property'); // 调用Blazor组件的JS可调用方法 window.DotNet.invokeMethodAsync( 'YourProjectAssemblyName', // 替换为你的项目程序集名称 'UpdateForecastProperty', forecastId, targetProperty, newValue ); } }); };
3. 在Blazor组件中实现数据更新方法
添加带有[JSInvokable]特性的方法,接收JS传递的参数,找到对应的WeatherForecast项并更新属性,最后调用StateHasChanged()触发组件重新渲染。
using Microsoft.JSInterop; using System.Collections.Generic; using System.Linq; public partial class WeatherForecastComponent { [Inject] private IJSRuntime JSRuntime { get; set; } private List<WeatherForecast> forecasts = new(); protected override async Task OnInitializedAsync() { // 模拟从服务获取初始数据 forecasts = await GetSampleForecasts(); } // 在组件首次渲染完成后初始化Numpad protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await JSRuntime.InvokeVoidAsync("initNumpad"); } } // 供JS调用的方法,更新WeatherForecast属性 [JSInvokable] public void UpdateForecastProperty(int forecastId, string targetProperty, string newValue) { var targetForecast = forecasts.FirstOrDefault(f => f.Id == forecastId); if (targetForecast == null) return; // 根据目标属性名更新对应值(这里以TemperatureC为例,可扩展其他数字属性) switch (targetProperty) { case "TemperatureC": if (int.TryParse(newValue, out int tempC)) { targetForecast.TemperatureC = tempC; } break; case "TemperatureF": if (int.TryParse(newValue, out int tempF)) { targetForecast.TemperatureF = tempF; } break; // 其他需要修改的数字属性 } // 触发组件重新渲染,同步DOM与数据源 StateHasChanged(); } // 模拟数据获取方法 private Task<List<WeatherForecast>> GetSampleForecasts() { var sampleData = new List<WeatherForecast> { new WeatherForecast { Id = 1, Date = DateOnly.FromDateTime(DateTime.Now), TemperatureC = 1, Summary = "Freezing" }, new WeatherForecast { Id = 2, Date = DateOnly.FromDateTime(DateTime.Now.AddDays(1)), TemperatureC = 14, Summary = "Bracing" }, new WeatherForecast { Id = 3, Date = DateOnly.FromDateTime(DateTime.Now.AddDays(2)), TemperatureC = -1, Summary = "Chilly" } }; return Task.FromResult(sampleData); } } // WeatherForecast模型示例 public class WeatherForecast { public int Id { get; set; } public DateOnly Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string? Summary { get; set; } }
关键注意事项
- 程序集名称:
invokeMethodAsync的第一个参数是你的项目程序集名称,可在项目属性的"应用"选项卡中查看。 - 不可变类型处理:如果
WeatherForecast是record(不可变类型),不能直接修改属性,需替换整个对象:var index = forecasts.FindIndex(f => f.Id == forecastId); if (index != -1) { forecasts[index] = forecasts[index] with { TemperatureC = tempC }; } - 数值校验:务必在.NET侧做数值转换校验(如
TryParse),避免非法输入导致报错。 - 渲染时机:必须在
OnAfterRenderAsync中初始化Numpad,确保Blazor已完成DOM渲染,否则JS无法找到目标单元格。
内容的提问来源于stack exchange,提问作者Hesam
相关产品推荐
相关产品推荐

