Hello Blazor:(10)按需加载JavaScript脚本

前言

Blazor支持执行JavaScript脚本,通常是将脚本放在wwwroot/index.html(Blazor WebAssembly)或Pages/_Host.cshtml(Blazor Server)中。

但是,这种方式会将所有JS方法用全局函数加载,即使某些方法只需要在特定组件中使用。既影响加载性能,又会造成全局污染。

JavaScript隔离

1. 标准方式

从.NET 5.0开始,Blazor支持在标准JavaScript模块中启用 JavaScript隔离(https://docs.microsoft.com/zh-cn/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-5.0#javascript-isolation-in-javascript-modules)。

实现方式如下:

  • 首先,在wwwroot目录下创建独立的js文件定义JS模块,比如scripts.js,

export function showPrompt(message) {
  return prompt(message, 'Type anything here');
}
  • 在Blazor组件中,使用IJSRuntime将模块作为IJSObjectReference导入

  • 然后,使用IJSObjectReference从模块调用导出的JS函数,代码如下:

@page "/fetchdata"
@inject IJSRuntime JS

<p>
    <button @onclick="TriggerPrompt">按需加载JavaScript脚本</button>
</p>

<p>
    @result
</p>

@code {
    private IJSObjectReference module;
    private string result;

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

    private async Task TriggerPrompt()
    {
        result = await module.InvokeAsync<string>("showPrompt", "输入文字:");
    }
}

可以看到,JS文件在访问页面时才加载,并且运行正常:

2. libman方式

但是,这种方式有一个缺点,文件必须放在wwwroot目录下

我更希望,JS文件和对应的Blazor组件放在一起,类似这样:

  • 右键单击项目,选择"管理客户端库",修改创建的libman.json文件内容如下:

{
  "version": "1.0",
  "defaultProvider": "filesystem",
  "libraries": [
    {
      "library": "Pages",
      "files": [
        "FetchData.razor.js"
      ],
      "destination": "wwwroot/"
    }
  ]
}
  • 右键单击libman.json,选择“生产时启用还原客户端库”。

  • 修改FetchData.razor代码如下:

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

再次运行, 工作正常。

3. 内嵌资源方式

上述方式虽然实现了效果,但是JS文件还是放在了wwwroot目录下,只是工具帮你进行的复制操作

如果你就是不希望wwwroot下有多余文件,可以尝试下面的方式。

  • 修改JS文件属性"生成操作",设置为"嵌入的资源"。

  • 修改FetchData.razor代码如下, 将资源文件作为JS代码加载:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        string scriptContent;
        using (var stream = this.GetType().Assembly.GetManifestResourceStream(this.GetType().Assembly.GetName().Name + ".Pages.FetchData.razor.js"))
        {
            using (var sr = new System.IO.StreamReader(stream))
            {
                scriptContent = await sr.ReadToEndAsync();
            }
        }

        module = await JS.InvokeAsync<IJSObjectReference>("import", "data:text/javascript;base64," + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(scriptContent)));
    }
}

再次运行, 同样工作正常,而且wwwroot下没有增加文件。

结论

今天,我们介绍了按需加载JavaScript脚本的标准方式及2种变种,你可以按照你的喜好选择使

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值