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不知道要提取事件的哪个字段。
修改步骤:
调整事件参数类的序列化映射
给InputValueChangeEventArgs的属性添加JSON序列化特性,同时遵循C#命名规范:using System.Text.Json.Serialization; public class InputValueChangeEventArgs : EventArgs { [JsonPropertyName("detail")] public string? Detail { get; set; } }更新自定义事件处理器配置
在EventHandler特性中明确指定要提取的事件字段为detail:[EventHandler("onvalueChange", typeof(InputValueChangeEventArgs), enableStopPropagation: true, enablePreventDefault: true, fieldName: "detail")] public static class EventHandlers { }重新编译项目
Blazor的自定义事件绑定逻辑是编译时生成的,修改后必须重新编译才能让新的字段映射生效。
验证
重新运行项目后,InputChanged方法中的Detail属性就能正确获取到输入框的当前文本值,WebSocket消息中的eventFieldInfo也会包含detail字段的映射信息。
内容的提问来源于stack exchange,提问作者Nelladel
相关产品推荐
相关产品推荐

