如何在Blazor中调用JavaScript类构造函数实例化对象
报错核心原因
你的代码有两个逻辑问题:
- Blazor JS互操作的
Invoke/InvokeAsync方法第一个参数仅支持传入可访问的函数/属性路径,不识别new 类名这类JS表达式语法。传入"new THREE.Scene"时,运行时会尝试查找名为new的全局对象下的THREE.Scene属性,自然找不到对应值。 - 你导入的是three.js的ES模块版本,这类模块不会向全局
window挂载THREE对象,所有导出的类、方法都直接挂载在导入拿到的模块实例引用上,全局作用域下根本不存在THREE变量。
无自定义JS包装的实现方案
不需要单独编写JS包装函数,Blazor本身就支持直接实例化JS类,根据你使用的.NET版本选择对应写法即可:
.NET 6及以上版本(推荐)
.NET 6开始IJSObjectReference/IJSInProcessObjectReference原生提供构造函数调用能力,写法最简洁:
// 导入three.js模块,建议将three.module.js放到项目wwwroot目录本地引用,避免远程CDN跨域、CSP拦截问题 var threeModule = await JS.InvokeAsync<IJSInProcessObjectReference>( "import", "./three.module.js" ); // 从模块上拿到Scene构造函数引用(.NET 7+可以用GetProperty扩展方法,低版本用Reflect.get取属性) var sceneCtor = await JS.InvokeAsync<IJSInProcessObjectReference>( "Reflect.get", threeModule, "Scene" ); // 直接调用构造函数实例化,等价于JS中的 new Scene() var scene = sceneCtor.InvokeNew<IJSInProcessObjectReference>(); // 带参数的构造函数直接按顺序传参即可,比如透视相机实例化 var cameraCtor = await JS.InvokeAsync<IJSInProcessObjectReference>( "Reflect.get", threeModule, "PerspectiveCamera" ); var camera = cameraCtor.InvokeNew<IJSInProcessObjectReference>(75, 1920d/1080d, 0.1, 1000);
.NET 5及更低版本
低版本没有原生InvokeNew方法,可以直接调用JS内置全局APIReflect.construct实现等价的new操作,完全不需要自定义JS代码:
var threeModule = await JS.InvokeAsync<IJSInProcessObjectReference>( "import", "./three.module.js" ); // 取模块上的Scene构造函数 var sceneCtor = await JS.InvokeAsync<IJSInProcessObjectReference>( "Reflect.get", threeModule, "Scene" ); // 调用JS内置的Reflect.construct执行实例化,第二个参数为构造函数参数数组 var scene = await JS.InvokeAsync<IJSInProcessObjectReference>( "Reflect.construct", sceneCtor, Array.Empty<object>() ); // 带参数的构造函数写法 var cameraCtor = await JS.InvokeAsync<IJSInProcessObjectReference>( "Reflect.get", threeModule, "PerspectiveCamera" ); var camera = await JS.InvokeAsync<IJSInProcessObjectReference>( "Reflect.construct", cameraCtor, new object[] {75, 1920d/1080d, 0.1, 1000} );
注意事项
- 所有通过JS互操作拿到的
IJSObjectReference实例用完之后必须调用Dispose()释放,否则会造成内存泄漏。 - 不建议直接引用远程CDN上的JS模块,容易触发跨域限制、CSP拦截,也可能因为版本变动导致代码失效,把依赖的JS文件下载到本地wwwroot目录引用是最稳妥的方案。
内容的提问来源于stack exchange,提问作者Jotto
相关产品推荐
相关产品推荐

