Blazor 服务器 Microsoft.JSInterop.JSException:“值 'window.resizeListener' 不是函数

Blazor Server Microsoft.JSInterop.JSException: "The value 'window.resizeListener' is not a function

我正在创建一个 Blazor Server 应用程序,我想使用 C# 代码对浏览器调整大小事件做出反应。因此我#m 遵循本教程:https://jakewaro.medium.com/detecting-browser-resize-in-server-side-blazor-apps-8d75bbab4d37

当我启动应用程序时出现异常:

Microsoft.JSInterop.JSException: "The value 'window.resizeListener' is not a function.
Error: The value 'window.resizeListener' is not a function.
    at p (http://localhost:60096/_framework/blazor.server.js:8:31071)
    at http://localhost:60096/_framework/blazor.server.js:8:31614
    at new Promise (<anonymous>)
    at e.beginInvokeJSFromDotNet (http://localhost:60096/_framework/blazor.server.js:8:31587)
    at http://localhost:60096/_framework/blazor.server.js:1:20052
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (http://localhost:60096/_framework/blazor.server.js:1:20022)
    at e.processIncomingData (http://localhost:60096/_framework/blazor.server.js:1:18006)
    at e.connection.onreceive (http://localhost:60096/_framework/blazor.server.js:1:11091)
    at WebSocket.i.onmessage (http://localhost:60096/_framework/blazor.server.js:1:39007)"

在此命令中:等待 JS.InvokeAsync("resizeListener", DotNetObjectReference.Create(this));

我不确定,为什么这个方法调用 window.resizeListener 而且这个异常只在我第一次加载网站时发生。但是,当我重新加载页面时,代码不起作用。

相关代码如下:

function resizeListener(dotnethelper) {
$(window).resize(() => {
    let browserHeight = $(window).innerHeight();
    let browserWidth = $(window).innerWidth();
    dotnethelper.invokeMethodAsync('SetBrowserDimensions', browserWidth, browserHeight).then(() => {
        // success, do nothing
    }).catch(error => {
        console.log("Error during browser resize: " + error);
    });
});
}

protected override void OnInitialized()
{
    // Init Browser service with Javascript runtime        
    Browser.Init(JS);
    Browser.Resize += UpdatedBrowserWidth;
}

protected void UpdatedBrowserWidth(object sender, int width)
{
    if (!bigWindowSize && width >= 1000)
    {
        bigWindowSize = true;
        base.StateHasChanged();
    }
    else if (bigWindowSize && width < 1000)
    {
        bigWindowSize = false;
        base.StateHasChanged();
    }
}

public class BrowserService
{
    private IJSRuntime JS = null;
    public event EventHandler<int> Resize;
    private int browserWidth;
    private int browserHeight;
    public async void Init(IJSRuntime js)
    {
        // enforce single invocation            
        if (JS == null)
        {
            this.JS = js;
            await JS.InvokeAsync<string>("resizeListener", DotNetObjectReference.Create(this));
        }
    }

    [JSInvokable]
    public void SetBrowserDimensions(int jsBrowserWidth, int jsBrowserHeight)
    {
        browserWidth = jsBrowserWidth;
        browserHeight = jsBrowserHeight;
        // For simplicity, we're just using the new width
        this.Resize?.Invoke(this, jsBrowserWidth);
    }
}

所以,经过长时间的反复试验,我终于有了解决方案:

它是将 JavaScript 代码直接包含到 _Hosts 文件中,如下所示:

 <script>
    window.resizeListener = function(dotnethelper) {
        $(window).resize(() => {
            let browserHeight = $(window).innerHeight();
            let browserWidth = $(window).innerWidth();
            dotnethelper.invokeMethodAsync('SetBrowserDimensions', browserWidth, browserHeight).then(() => {
                // success, do nothing
            }).catch(error => {
                console.log("Error during browser resize: " + error);
            });
        });
    }
</script>

而不是将 int 放在一个单独的 .js 文件中,它只在 _Hosts 文件中引用。

我还把代码从 OnInitialized 方法移到了 OnRenderAsync 方法(在 if(firstrender) 中)

我认为您使用了错误的生命周期方法。 Blazor 服务器应用程序不允许任何生命周期方法中的 Javascript 函数,OnAfterRenderAsync 除外。这不会发生在 WebAssembly 应用程序中,因为它是在客户端上加载的。我不知道你是如何呈现你的页面的,但我假设你设置了“ServerPrerendered”选项,而不是“Server”。

这不会在您的 _Host 文件中发生的原因是因为它始终作为预呈现文件发送到客户端,并且您显然在普通 cshtml 文件中没有任何生命周期方法。要解决此问题,您应该仅在确定页面已呈现后才执行 javascript。

protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            // JS code here
        }
    }