You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor组件库JS隔离调用TypeScript库showHello函数报错求助

问题描述

我有一个用TypeScript编写的JavaScript库,编译后的代码如下:

(function(f) {
    if (typeof exports === "object" && typeof module !== "undefined") {
        module.exports = f()
    } else if (typeof define === "function" && define.amd) {
        define([], f)
    } else {
        var g;
        if (typeof window !== "undefined") {
            g = window
        } else if (typeof global !== "undefined") {
            g = global
        } else if (typeof self !== "undefined") {
            g = self
        } else {
            g = this
        }
        g.richTextEditor = f()
    }
}
)(function() {
    var define, module, exports;
    return (function() {
        function r(e, n, t) {
            function o(i, f) {
                if (!n[i]) {
                    if (!e[i]) {
                        var c = "function" == typeof require && require;
                        if (!f && c)
                            return c(i, !0);
                        if (u)
                            return u(i, !0);
                        var a = new Error("Cannot find module '" + i + "'");
                        throw a.code = "MODULE_NOT_FOUND",
                        a
                    }
                    var p = n[i] = {
                        exports: {}
                    };
                    e[i][0].call(p.exports, function(r) {
                        var n = e[i][1][r];
                        return o(n || r)
                    }, p, p.exports, r, e, n, t)
                }
                return n[i].exports
            }
            for (var u = "function" == typeof require && require, i = 0; i < t.length; i++)
                o(t[i]);
            return o
        }
        return r
    }
    )()({
        1: [function(require, module, exports) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: true
            });
            exports.showHello = void 0;
            const greet_1 = require("./greet");
            function showHello(divName, name) {
                const elt = document.getElementById(divName);
                elt.innerText = (0,
                greet_1.sayHello)(name);
            }
            exports.showHello = showHello;

        }
        , {
            "./greet": 2
        }],
        2: [function(require, module, exports) {
            "use strict";
            Object.defineProperty(exports, "__esModule", {
                value: true
            });
            exports.sayHello = void 0;
            function sayHello(compiler) {
                return `Hello from ${compiler}`;
            }
            exports.sayHello = sayHello;

        }
        , {}]
    }, {}, [1])(1)
});

我尝试在Blazor中通过JSInterop调用该库的showHello函数,使用的C#代码如下:

public class TypeScriptInterop
{
    private readonly Lazy<Task<IJSObjectReference>> _moduleTask;

    public TypeScriptInterop(IJSRuntime jsRuntime)
    {
        _moduleTask = new(()=>
        jsRuntime.InvokeAsync<IJSObjectReference>("import", "./_content/Blazored.RichTextEditor/js/bundle.generated.js").AsTask());
    }

    public async ValueTask TsButtonClicked()
    {
        var javaScript = await _moduleTask.Value;
        if (_moduleTask.IsValueCreated)
        {
            Console.WriteLine("Captured Js");
        }
        await javaScript.InvokeVoidAsync("richTextEditor.showHello", "greeting", "Ubhaya");
    }
}

运行时出现以下错误:

WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Could not find 'richTextEditor.showHello' ('richTextEditor' was undefined).

直接在Blazor WASM项目的index.html中通过<script src="./_content/Blazored.RichTextEditor/js/bundle.generated.js"></script>引入该JS文件就能正常运行。但我正在开发Blazor组件库,希望采用JS隔离的方式实现,请问当前方案下如何解决这个问题?


解决方案

问题核心:当用Blazor的JS隔离方式(import)加载模块时,模块不会自动将richTextEditor挂载到全局对象(如window),但你的C#代码仍在尝试调用全局作用域下的richTextEditor.showHello,导致找不到对象。

以下是两种可行的解决方式:

方式1:修改TypeScript源码与打包配置(推荐)

如果能修改TS源码,直接将需要暴露的方法以ES模块格式导出:

// 主TS文件
import { sayHello } from './greet';

export function showHello(divName: string, name: string) {
    const elt = document.getElementById(divName);
    if (elt) {
        elt.innerText = sayHello(name);
    }
}

然后调整打包工具(如Webpack、Rollup)的配置,将输出格式设置为ES模块(output.module: true或类似配置)。编译后的JS会包含export语句,不再依赖全局挂载。

方式2:适配现有打包后的JS文件

如果无法修改源码或打包配置,可在现有JS文件末尾添加一行代码,显式导出模块内容:

// 在现有打包代码的最后添加
export const showHello = window.richTextEditor.showHello;
// 或导出整个对象
// export const richTextEditor = window.richTextEditor;

这样Blazor通过import加载模块时,就能获取到导出的方法。

调整C#调用代码

无论采用哪种方式,都需要修改C#的调用逻辑,直接调用模块导出的方法,而非全局对象:

public async ValueTask TsButtonClicked()
{
    var javaScript = await _moduleTask.Value;
    // 如果导出的是单个showHello方法
    await javaScript.InvokeVoidAsync("showHello", "greeting", "Ubhaya");
    // 如果导出的是整个richTextEditor对象
    // var editor = await javaScript.InvokeAsync<IJSObjectReference>("richTextEditor");
    // await editor.InvokeVoidAsync("showHello", "greeting", "Ubhaya");
}

注意事项

  • 确保打包后的JS文件是ES模块格式(包含export语句),Blazor的JS隔离仅支持ES模块。
  • JS隔离的核心是避免污染全局作用域,因此尽量采用模块导出的方式暴露方法,不要依赖全局变量。

内容的提问来源于stack exchange,提问作者Ubhaya Kalanamiththa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:09:56