我正在创建一个Blazor Server应用程序,我想用c#代码对浏览器调整大小事件做出反应。因此,我遵循本教程:https://jakewaro.medium.com/detecting-browser-resize-in-server-side-blazor-apps-8d75bbab4d37
当我启动应用程序时,我得到这个Exception:
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));
我不确定,为什么这个方法调用窗口。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);
}
}
我认为您使用了错误的生命周期方法。Blazor服务器应用程序不允许任何生命周期方法中的Javascript函数,除了OnAfterRenderAsync。这不会发生在WebAssembly应用程序中,因为它是在客户端加载的。我不知道你如何渲染你的页面,但我假设你有选项"ServerPrerendered"设置,而不是"Server"
在_Host文件中没有发生这种情况的原因是因为它总是作为预呈现文件发送给客户端,并且显然在普通cshtml文件中没有任何生命周期方法。为了解决这个问题,你应该只在你确定页面已经渲染后才执行javascript。
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// JS code here
}
}
所以,经过长时间的反复试验,我终于有了解决方案:
将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(first strender)中)