Blazor多数场景可不写JavaScript,但需正确调用:JS须外置加载,通过IJSRuntime调用;Server与WASM机制不同,Server禁OnInitialized调JS,WASM支持IJSInProcessRuntime;JS回调C#需DotNetObjectReference并手动释放防泄漏。

Blazor 不是“不用写 JavaScript”,而是让你**多数场景可以不写 JavaScript**——但该用的时候还得用,而且得用对方式。直接在组件里写 JS 会破坏服务端预渲染、导致 SSR 失效,甚至引发 JSRuntime.InvokeAsync 在服务端未初始化的异常。
Blazor Server 和 Blazor WebAssembly 的 JS 调用机制完全不同
Blazor Server 通过 SignalR 建立 .NET 与浏览器之间的长连接,IJSRuntime 实际是代理调用;Blazor WebAssembly 则是在 WASM 运行时中直接桥接 JS 全局对象。这意味着:
-
IJSRuntime.InvokeVoidAsync("foo")在 Server 模式下可能因连接中断静默失败,在 WASM 下则会抛出JSException - Server 模式下不能在
OnInitialized中立即调用 JS(此时 DOM 可能未挂载),WASM 下可以但需确保OnAfterRender已触发 -
Microsoft.JSInterop.IJSInProcessRuntime仅在 WASM 中可用,Server 中调用会报NotSupportedException
从 C# 调用 JS 函数必须走 IJSRuntime,不能直接写 script 标签内联
在 .razor 文件里写 <script>function sayHi() { alert('hi') }</script> 是无效的:Blazor 组件生命周期管理 DOM,手动插入的 script 不会被执行,且每次重渲染都会被移除。
正确做法是:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 把 JS 函数定义在
wwwroot/js/site.js(或任意静态资源路径),并在index.html(WASM)或_Host.cshtml(Server)中通过<script src="js/site.js"></script>加载 - 在组件中注入
@inject IJSRuntime JSRuntime - 调用时用
await JSRuntime.InvokeVoidAsync("sayHi")或await JSRuntime.InvokeAsync<string>("getUserId")</string> - 如果 JS 函数需要访问组件实例(比如回调后更新状态),必须用
DotNetObjectReference.Create(this)传入,并在 JS 中保存引用——否则组件销毁后回调会 crash
JS 回调 C# 时,DotNetObjectReference 必须手动释放
常见错误是只创建不释放,导致内存泄漏和跨组件调用混乱。例如在 JS 中绑定事件后未清理:
window.registerClickHandler = (dotnetRef) => {
document.body.addEventListener('click', () => dotnetRef.invokeMethodAsync('HandleClick'));
};
对应 C# 端必须在 Dispose 或 OnAfterRender 中显式释放:
- 组件类实现
IDisposable - 在
Dispose()中调用_objRef?.Dispose()(其中_objRef是DotNetObjectReference.Create(this)创建的) - 如果组件支持热重载(Hot Reload),
Dispose可能被多次调用,需加 null 检查
最易被忽略的是:JS 代码里对 DotNetObjectReference 的引用不会自动失效,即使 C# 对象已被 GC,JS 仍可能尝试调用已释放的实例——这会导致 System.ObjectDisposedException 或静默失败。务必在 JS 侧也做存在性检查,比如 if (dotnetRef && !dotnetRef.isDisposed)。

















