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

Blazor封装JS Web Component时CustomEvent的detail值为null问题

Blazor封装原生Web组件时自定义事件detail属性为null的问题解决

我们正在为原生JavaScript Web组件库构建Blazor封装。当用户修改输入框内容时,组件会触发valueChange自定义事件,我们需要捕获该事件并获取CustomEvent中包含输入框当前文本的detail属性,但实际测试中detail始终为null。

测试观察到的现象

  • 在document上添加valueChange事件监听器,可正常获取填充完成的detail属性;
  • 在开发者工具中给Blazor的blazor.server.js里的onGlobalEvent(e)方法加断点,能看到detail属性已填充;
  • 查看WebSocket消息时,内容包含......BeginInvokeDotNetFromJS..1..DispatchEventAsync..I[{"eventHandlerId":7,"eventName":"valueChange","eventFieldInfo":null},{}],怀疑eventFieldInfo: null与问题相关;
  • 在Counter.razor的InputChanged()方法中设断点,发现detail属性为null。

相关代码

library-input.js

#updateValue(value) {
    // ... 更新原生value属性的逻辑

    const valueEvent = new CustomEvent("valueChange", {
        detail: this.#value,
        bubbles: true,
    });

    this.dispatchEvent(valueEvent);
}

libraryInput.razor

@inject IJSRuntime JSRuntime
@namespace BlazorWrapperForLibrary
@using System.Text.Json

<lib-input @ref="libInput" @onvalueChange="ValueChanged">
</lib-input>

@code {
    private ElementReference libInput;
    private const string JAVASCRIPT_FILE = "/js/library-components.js";
    private const string INTEROP_FILE = "/js/lib-input.interop.js";

    private IJSObjectReference? Module { get; set; }
    private IJSObjectReference? Interop { get; set; }
    
    [Parameter]
    public string? Value { get; set; }

    [Parameter]
    public EventCallback<InputValueChangeEventArgs> ValueChanged {get; set;}

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            Module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", JAVASCRIPT_FILE);
            Interop = await JSRuntime.InvokeAsync<IJSObjectReference>("import", INTEROP_FILE);
        }
    }
}

CustomEvents.cs

public class InputValueChangeEventArgs : EventArgs
{
    public string? detail { get; set; }
}

[EventHandler("onvalueChange", typeof(InputValueChangeEventArgs), enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}

Counter.razor

@page "/counter"
    <LibInput Value="newValue" ValueChanged="@((InputValueChangeEventArgs value) => InputChanged(value))">
    </LibInput>
@code {
    private string newValue = "undefined";

    private void InputChanged(InputValueChangeEventArgs value)
    {
        Console.WriteLine(value.detail);
    }
}

问题原因及解决方法

问题核心是Blazor默认不会自动映射CustomEvent的detail属性到自定义事件参数类中,WebSocket消息里的eventFieldInfo: null也说明Blazor不知道要提取事件的哪个字段。

修改步骤:

  1. 调整事件参数类的序列化映射
    给InputValueChangeEventArgs的属性添加JSON序列化特性,同时遵循C#命名规范:

    using System.Text.Json.Serialization;
    
    public class InputValueChangeEventArgs : EventArgs
    {
        [JsonPropertyName("detail")]
        public string? Detail { get; set; }
    }
    
  2. 更新自定义事件处理器配置
    在EventHandler特性中明确指定要提取的事件字段为detail:

    [EventHandler("onvalueChange", typeof(InputValueChangeEventArgs), 
        enableStopPropagation: true, 
        enablePreventDefault: true,
        fieldName: "detail")]
    public static class EventHandlers
    {
    }
    
  3. 重新编译项目
    Blazor的自定义事件绑定逻辑是编译时生成的,修改后必须重新编译才能让新的字段映射生效。

验证

重新运行项目后,InputChanged方法中的Detail属性就能正确获取到输入框的当前文本值,WebSocket消息中的eventFieldInfo也会包含detail字段的映射信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 10:02:42