且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Blazor Server:仅在某些页面上加载js脚本,而不是在所有页面上加载

更新时间:2023-12-01 23:11:46

如评论中所述,Blazor是SPA,因此任何加载的脚本都可以在Blazor页面上使用,因为它是同一页面.

As discussed in the comments, Blazor is an SPA so any loaded script is available on Blazor pages since it's the same page.

但是,您没有将它们全部列出在_Host.cshtml中,实际上,您可能只想在需要时才加载特定的脚本(例如,并非所有用户都使用特定的页面/需要脚本的组件).

However, you don't have to list them all in _Host.cshtml, and indeed you probably want to only load a specific script when it's needed (e.g. not all users use a particular page/component where the script is required).

可以使用JS Interop动态加载脚本.我创建了以下scriptLoader.js库并将其包含在_Host.cshtml中:

It is possible to load scripts dynamically using JS Interop. I created the following scriptLoader.js library and included this in _Host.cshtml:

// loadScript: returns a promise that completes when the script loads
window.loadScript = function (scriptPath) {
    // check list - if already loaded we can ignore
    if (loaded[scriptPath]) {
        console.log(scriptPath + " already loaded");
        // return 'empty' promise
        return new this.Promise(function (resolve, reject) {
            resolve();
        });
    }

    return new Promise(function (resolve, reject) {
        // create JS library script element
        var script = document.createElement("script");
        script.src = scriptPath;
        script.type = "text/javascript";
        console.log(scriptPath + " created");

        // flag as loading/loaded
        loaded[scriptPath] = true;

        // if the script returns okay, return resolve
        script.onload = function () {
            console.log(scriptPath + " loaded ok");
            resolve(scriptPath);
        };

        // if it fails, return reject
        script.onerror = function () {
            console.log(scriptPath + " load failed");
            reject(scriptPath);
        }

        // scripts will load at end of body
        document["body"].appendChild(script);
    });
}
// store list of what scripts we've loaded
loaded = [];

这将创建一个script元素,并将其追加到文档的body元素中.由于脚本将异步加载,因此它返回一个Promise,因此您在C#代码中需要await.

This creates a script element and appends to the body element of the document. It returns a promise since the script will load asynchronously, so you need await in the C# code.

loaded数组在那里,以避免再次重新加载脚本.除非用户刷新页面,否则任何脚本一旦加载,都将保持加载状态.因此,负载仅发生一次.

The loaded array is there to avoid re-loading the script again. Any script, once loaded, stays loaded unless the user refreshes the page. So the load only occurs once.

在需要确保已加载库的页面/组件上,需要注入IJSruntime ...

On a page/component where I need to ensure a library is loaded, I will need to inject the IJSruntime...

@inject IJSRuntime jsRuntime

然后调用它..

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        // invoke script loader
        Console.WriteLine("Loading jQuery");
        await jsRuntime.InvokeVoidAsync("loadScript", "https://code.jquery.com/jquery-3.4.1.js");
        await jsRuntime.InvokeVoidAsync("loadScript", "myJQueryTest.js");

        Console.WriteLine("Invoking jQuery");

        await jsRuntime.InvokeVoidAsync("setH1", "Hello world!");

        Console.WriteLine("Invoked JQuery");

        await base.OnAfterRenderAsync(firstRender);
    }

myJQueryTest.js很简单:

window.setH1 = function (message) {
    $('h1').text(message);
}

创建了示例存储库: https://github.com/conficient/BlazorDynamicScriptLoad