如何从Blazor C#代码调用静态JavaScript方法

6

首先,是我的JS代码:

class MyClass {
    static myMethod() {
        alert("TEST");
    }
}

我是这样注入我的JS运行时的:

[Inject] protected IJSRuntime Js { get; set; }

我想像这样调用一个静态方法:
Js.InvokeVoidAsync("MyClass.myMethod");

但是我遇到了一个错误:

Microsoft.JSInterop.JSException: 在 'window' 中找不到 'MyClass'。

有没有什么明智、合理的方法可以解决这个问题?或者只能通过在我的JS中添加 window.MyClass = MyClass 来解决?


4
不,那是实现它的方法。https://learn.microsoft.com/zh-cn/aspnet/core/blazor/javascript-interop?view=aspnetcore-3.0 - David Masterson
在JS中创建一个包装函数来调用类。这种方式有其缺陷,但当您还有一百万行代码需要调试时,快速简单也有其好处。 - user160357
2个回答

4
请尝试以下方法(假设为服务器端Blazor)。
在您的 _Host.cshtml 文件中:
(function () {
    window.MyClass = {
        myMethod: function () {
            return alert('TEST');
        }
    };
})();

在 .razor 文件中(顶部):

@*Inject JSRuntime to allow JavaScript Interop *@
@inject IJSRuntime JSRuntime

在您的 .razor 文件中的一个方法中:

await JSRuntime.InvokeAsync<string>(
            "MyClass.myMethod", null
            );

参见:Blazor JavaScript Interop


2
将其包装为IIFE的好处是什么?您仍然将MyClass注册到全局范围,因此封装是无用的,不是吗? - Postlagerkarte

0

是的,将您的方法注册到窗口对象是正确的。

源代码的相关部分可以在这里找到:

https://github.com/aspnet/Extensions/tree/master/src/JSInterop

看一眼,你会发现:

invokeJSFromDotNet: (identifier: string, argsJson: string) => { ... }

在哪里?

@param identifier 用于标识全局可访问的要调用的函数。

查看findJSFunction函数,你会发现其中检查给定标识符是否已注册到window对象中,如果没有,则生成您看到的错误:

function findJSFunction(identifier: string): Function {

(...)

    let result: any = window;
    let resultIdentifier = 'window';
    let lastSegmentValue: any;
    identifier.split('.').forEach(segment => {
      if (segment in result) {
        lastSegmentValue = result;
        result = result[segment];
        resultIdentifier += '.' + segment;
      } else {
        throw new Error(`Could not find '${segment}' in '${resultIdentifier}'.`);
      }
    });

嗯,类可以通过 eval 访问,当正确使用时并不邪恶。我制作了自己的“调用静态”和“创建实例”代码版本,我想知道是否有一种方法可以扩展 JSInterop 以使用这些方法。我的意思是我制作了一个扩展类,但它需要额外的 JS 来工作。 - Harry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接