【问题标题】:Call js generated from typescript in blazor using IJSObjectReference使用 IJSObjectReference 在 blazor 中调用从 typescript 生成的 js
【发布时间】:2020-11-19 21:58:06
【问题描述】:

您好,我有一个关于使用 Blazor 和 typescript 的问题。

我的打字稿:

namespace JSInteropWithTypeScript {

    export class Generator {
        public showAlert(): void {
            alert("INTEROP");
        }
    }

    export function Load(): void {
        window['generator'] = new Generator();
    }
}

JSInteropWithTypeScript.Load();

这里是生成的JS:

var JSInteropWithTypeScript;
(function (JSInteropWithTypeScript) {
    var Generator = /** @class */ (function () {
        function Generator() {
        }
        Generator.prototype.showAlert = function () {
            alert("INTEROP");
        };
        return Generator;
    }());
    JSInteropWithTypeScript.Generator = Generator;
    function Load() {
        window['generator'] = new Generator();
    }
    JSInteropWithTypeScript.Load = Load;
})(JSInteropWithTypeScript || (JSInteropWithTypeScript = {}));
JSInteropWithTypeScript.Load();
//# sourceMappingURL=generator.js.map

接下来我想调用编译后的 js 脚本,所以我有一个带按钮的简单组件:

@namespace Components.Reports.Components.Generator
@inherits ControlsBase

<button class="btn btn-success" @onclick="ShowAlert"> BUTON </button>

在这个组件的基类中,我想延迟加载(所以我不需要在 _Host 中添加每个脚本,只需在需要时使用它们)这个脚本文件并调用这个函数,所以我做了这个装置:

public class ControlsBase : ComponentBase, IAsyncDisposable
{
    private readonly Lazy<Task<IJSObjectReference>> moduleTask;

    [Inject]
    protected IJSRuntime JsRuntime { get; set; }
    
    public ControlsBase()
    {
        Task<IJSObjectReference> jsInvokes() => this.JsRuntime.InvokeAsync<IJSObjectReference>("import", "./_content/Components/js/generator.js").AsTask();
        this. moduleTask = new Lazy<Task<IJSObjectReference>>(jsInvokes);
    }

    public async Task ShowAlert()
    {
        try
        {
            var module = await moduleTask.Value;
            await module.InvokeVoidAsync("showAlert");
        }
        catch (JSException jsException)
        {
            logger.Error($"Problem with js interop {jsException}");
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (moduleTask.IsValueCreated)
        {
            var module = await moduleTask.Value;
            await module.DisposeAsync();
        }
    }
}

所以现在我想调用它,我的问题/问题是当我调用编译后的 js 脚本时

找不到“showAlert”(“showAlert”未定义)。

当我使用原版代码时:

export function showAlert() {
  alert("INTEROP");
}

它有效。

那么我在打字稿方面做错了什么?

编辑

使用@Haytam 指南,我将我的 ts 重新制作为简单:

namespace JSInteropWithTypeScript {
    export class Generator {
        public ShowAlert(): void {
            alert("INTEROP");
        }
    }
}

function showAlert(): void {
    let generator = new JSInteropWithTypeScript.Generator();
    generator.ShowAlert();
}

然后编译成js:

var JSInteropWithTypeScript;
(function (JSInteropWithTypeScript) {
    var Generator = /** @class */ (function () {
        function Generator() {
        }
        Generator.prototype.ShowAlert = function () {
            alert("INTEROP");
        };
        return Generator;
    }());
    JSInteropWithTypeScript.Generator = Generator;
})(JSInteropWithTypeScript || (JSInteropWithTypeScript = {}));
function showAlert() {
    var generator = new JSInteropWithTypeScript.Generator();
    generator.ShowAlert();
}

但要正常工作,我需要在 js 中的函数之前手动添加导出。我知道导致此错误的原因是 TypeScript 默认情况下会生成 JavaScript 代码,该代码旨在通过各种迎合导出的包管理器使用和模块。此类工具通常是 Node.js 或 WebPack。我可以使用 tsconfig 将其关闭:

{
  "compilerOptions": {
    "module": "none"
   }
}

但仍然只有当函数在 js 中标记为导出时,js 互操作才有效。任何想法如何处理?

EDIT2:

我认为问题在于延迟加载,将生成的 js 脚本添加为静态资源:

 <script src="_content/Components/js/generator.js"></script>

和使用的代码:

    public async Task OnClick()
    {
        try
        {
            await this.JsRuntime.InvokeVoidAsync("showAlert");
        }
        catch (JSException jsException)
        {
            logger.Error($"Problem with js interop {jsException}");
        }
    }

在我的组件库中,它还活着,但仍然只是出于好奇,我想让这个延迟加载。任何建议将不胜感激。

【问题讨论】:

  • 可以把TS生成的JS贴出来吗?
  • 没问题,刚刚添加
  • 2021 年 9 月,此问题仍然存在。对于任何寻求解决此问题的人来说,都没有——至少目前是这样。您必须在_Host.cshtml 的脚本标记中指定 js 文件。

标签: c# typescript blazor blazor-server-side


【解决方案1】:

我在这里看到两个问题:

  1. Blazor JS 隔离适用于 JavaScript Modules。不再需要将函数放入window,这就是他们首先添加此隔离的原因。
  2. 由于 Blazor JS Isolation 与 JS 模块一起使用,因此它需要直接导出函数。我相信无论你怎么尝试,使用 TS 类生成的 JS 都行不通。

我认为你应该尝试直接导出函数。

编辑

根据您的最新编辑,这不起作用吗?

export function showAlert(): void {
    let generator = new JSInteropWithTypeScript.Generator();
    generator.ShowAlert();
}

【讨论】:

  • 感谢您的回答,我删除了该加载语句并将函数显示警报移到类和命名空间之外,但是我需要在没有它的情况下在编译的 js 中手动添加导出 blazor 看不到该函数,当我添加时它在 TS 我得到的出口没有定义异常。我会更新我的问题以获取更多详细信息。
  • @WojciechSzabowicz 对我的答案进行了编辑,我相信您也可以在 TS 中使用 export 关键字吗?
  • 不是我的情况(但我没有使用 npm,因为我写的所有信息都告诉我要关闭导出或初始化 npm)当我在 ts 中的函数之前添加导出时,在 js 中导出看起来像: 出口.showAlert = showAlert;并调用它会引发异常。
  • @WojciechSzabowicz 你有没有设法解决出口异常?我自己也遇到过这个。
  • @Andrew,哦忘了这个问题了。如果我在 _Host.cshtml 中没记错的话,我已将 更改为
猜你喜欢
  • 2022-12-31
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 2019-05-15
  • 2018-12-17
  • 2016-08-11
相关资源
最近更新 更多