Blazor通过JS调用C#方法无法更新UI,非静态方法调用报错如何解决?
问题根因
你的推测完全正确:
- 标记
[JSInvokable]的静态方法属于程序集/类层级,不属于具体的组件实例,无法访问组件的非静态成员变量,自然也无法触发对应组件的UI重渲染 - 你当前使用的
DotNet.invokeMethodAsync('程序集名','方法名')是全局静态调用,仅会检索对应程序集下的公共静态可调用方法,所以去掉static修饰符后会提示找不到方法
解决方案:使用组件实例引用调用实例方法
Blazor提供了DotNetObjectReference用来把组件实例暴露给JS侧,通过实例引用即可调用组件的实例方法,完整实现步骤如下:
1. 组件侧生成实例引用并传递给JS
在你的组件代码中添加如下逻辑:
// 注入JS运行时 [Inject] private IJSRuntime JS { get; set; } // 存储组件实例引用,替换尖括号内为你实际的组件类名 private DotNetObjectReference<你的组件类名>? _componentRef; // ParaContent是你要更新的组件成员 private string ParaContent { get; set; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { // 创建当前组件的实例引用 _componentRef = DotNetObjectReference.Create(this); // 将引用传递给JS侧存储 await JS.InvokeVoidAsync("window.saveBlazorComponentRef", _componentRef); } } // 组件销毁时释放引用,避免内存泄漏 public void Dispose() { _componentRef?.Dispose(); }
2. 修改GetCountryInformation为实例方法
去掉static修饰符,更新后代码如下:
[JSInvokable] public Task<string> GetCountryInformation(string selectedCountry) { string result = MyService.GetCompanyInfo(selectedCountry); ParaContent = result; // 手动触发UI重渲染 StateHasChanged(); return Task.FromResult(result); }
3. 修改JS侧调用逻辑
不再使用全局静态调用,改为用存储的组件实例引用调用方法:
// 存储Blazor组件实例引用 let blazorComponentRef = null; // 供Blazor侧调用存储引用 window.saveBlazorComponentRef = (ref) => { blazorComponentRef = ref; }; function onClick(e) { $('#countryName').text(e.name); // 改用组件实例调用方法,不需要传程序集名 blazorComponentRef.invokeMethodAsync('GetCountryInformation', e.name) .then(message => { $('#countryInfo').text(message); }); }
注意事项
- 如果页面存在多个同类型组件实例,需要自行区分存储每个实例的引用,避免覆盖导致调用错误
- 实例方法的名称需要和JS侧
invokeMethodAsync传入的第一个参数完全一致,若要自定义别名可以给[JSInvokable]传入参数:[JSInvokable("自定义方法名")]
内容的提问来源于stack exchange,提问作者Harry Birimirski
相关产品推荐
相关产品推荐

