Blazor 中的独立 JavaScript 与并置的 JS 文件

· 1 分钟阅读

如果您以前使用过 Blazor 和 JS Interop,那么您可能最终会得到一个巨大的 app.js 文件,其中充满了不同组件的随机函数。它有效,但很快就会变得混乱。幸运的是,有一种更简洁的方法:并置 JavaScript 文件。

这个想法

就像 CSS 隔离一样,Blazor 允许您在组件旁边放置一个 .razor.js 文件。 JavaScript 模块仅在组件实际需要时按需加载。无全局脚本,无污染。

设置它

假设我们有一个 Clipboard.razor 组件将文本复制到剪贴板。在其旁边创建一个名为 Clipboard.razor.js 的文件:

export function copyToClipboard(text) {
    navigator.clipboard.writeText(text).then(() => {
        console.log("Copied to clipboard!");
    });
}

请注意 export 关键字 - 这很重要。 Blazor 将其作为标准 ES 模块加载。

在 Blazor 中加载模块

在您的组件中,您使用 IJSRuntime 导入模块。该路径遵循约定:./_content/{ASSEMBLY_NAME}/{COMPONENT_PATH}.razor.js 对于库,或者只是当前项目的相对路径。

@inject IJSRuntime JS
@implements IAsyncDisposable

<button @onclick="Copy">Copy to clipboard</button>

@code {
    [Parameter]
    public string Text { get; set; }

    private IJSObjectReference? module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Clipboard.razor.js");
        }
    }

    private async Task Copy()
    {
        if (module is not null)
        {
            await module.InvokeVoidAsync("copyToClipboard", Text);
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

这里有几点需要注意:

  • 我们在 OnAfterRenderAsync 中加载模块,因为 JS Interop 在服务器端预渲染期间不可用
  • 我们用 IJSObjectReference 保留对模块的引用
  • 我们实现 IAsyncDisposable 在组件被销毁时清理模块

为什么这样更好

之前,我习惯将所有内容转储到一个 wwwroot/js/app.js 中。它有效,但查找函数很痛苦,而且每个页面都加载了它不需要的 JavaScript。使用并置的 JS 文件:

  • 每个组件都有自己的JavaScript
  • 模块仅在需要时才延迟加载
  • 没有全局函数名称冲突
  • 更容易维护和删除——当你删除组件时,你也删除了它的JS

路径问题

您传递给 import 的路径取决于您是在独立的 Blazor 应用程序中还是在 Razor 类库中。对于常规 Blazor 应用程序,该路径是相对于 wwwroot 的。 .razor.js 文件在构建时被复制到那里,因此您可以从项目中组件的位置引用它。

如果加载模块时遇到 404,请仔细检查路径并确保文件以 .razor.js 结尾,而不仅仅是 .js

希望你喜欢这篇文章!请随时通过任何社交媒体与我联系:@emimontesdeoca

资源