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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:50:25