Blazor,如何不断获得当前窗口宽度?

2022-08-03 00:00:00 javascript css blazor

我想在剃须刀页面中这样做:

@if (currentwidth<x)
{
   le code
}
else
{
    le other code
}

我已添加了Java脚本文件,并将其连接到一个实用程序服务,该实用程序服务在我获得静态宽度(我测试了该宽度)时即可工作。

js:

export function getCurrentWidth() {

    return window.addEventListener("resize", () => {
        window.innerWidth;
    });

}

UtilityService方法:

public async Task<double> GetCurrentWidth() 
        {
            var m = await GetModule();
            var result = await m.InvokeAsync<double>("getCurrentWidth");
            return result;
        }

Razor文件:

double width;

    protected async override Task OnInitializedAsync()
    {
        width = await utilityService.GetCurrentWidth();
    }

因此,问题是我不能从OnInitailzedAsync调用它,因为该函数只触发一次,所以我需要一个不断检查GetCurrentWIdth()方法的函数来检查调整大小。

在Blazor中有没有其他方法可以做到这一点,或者我可以使用什么方法/提前谢谢。


解决方案

首先我想指出,您可能不必使用Java脚本/C#代码来解决您的问题。如果您想要操作html中的内容,那么您最好使用css。但我会让你自己决定的。

但是,如果您确实需要如上所述的窗口宽度,那么我建议您向窗口注册一个侦听器(就像您已经做过的那样),并让该侦听器调用一个DotNet函数。使用静态方法实现这一点非常容易,但对于组件来说,这可能会有点棘手,因为您必须传递当前对象的对象引用。

[JsInvokable]指示此方法可以从Java脚本调用,这允许从Java脚本事件侦听器到DotNet进行通信。

CSharpFromJs.razor.cs

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Threading.Tasks;

public partial class CSharpFromJS
{
    private DotNetObjectReference<CSharpFromJS> _objectReference;
    public int WindowWidth { get; set; }


    [Inject]
    public IJSRuntime JSRuntime { get; set; }

    protected override void OnInitialized()
    {
        _objectReference = DotNetObjectReference.Create(this);
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await InitWindowWidthListener();
        }
    }

    [JSInvokable]
    public void UpdateWindowWidth(int windowWidth)
    {
        WindowWidth = windowWidth;
        StateHasChanged();
    }

    private async Task InitWindowWidthListener()
    {
        await JSRuntime.InvokeVoidAsync("AddWindowWidthListener", _objectReference);
    }

    public async ValueTask DisposeAsync()
    {
        await JSRuntime.InvokeVoidAsync("RemoveWindowWidthListener", _objectReference);
        _objectReference?.Dispose();
    }
}

CSharpFromJs.razor

@implements IAsyncDisposable

<h1>Window width: @WindowWidth</h1>

Java脚本

// Manages the registered event listeners so they can be disposed later
let windowEventListeners = {};

function AddWindowWidthListener(objReference) {
    let eventListener = () => UpdateWindowWidth(objReference);
    window.addEventListener("resize", eventListener);
    windowEventListeners[objReference] = eventListener;
}

function RemoveWindowWidthListener(objReference) {
    window.removeEventListener("resize", windowEventListeners[objReference]);
}

function UpdateWindowWidth(objReference) {
    objReference.invokeMethodAsync("UpdateWindowWidth", window.innerWidth);
}

您唯一需要注意的是组件被释放时。您应该删除DisposeAsync函数中已注册的处理程序,以确保它们不会仍被注册以防止内存泄漏。

This link可能会提供一些有关如何使用它的更好说明,但它们没有解释有关处置处理程序的部分。

注意:这只适用于.net5及更高版本,因为在此之前组件尚未实现IAsyncDisposable。如果出于某种原因您正在使用较早的版本,您可以使用IDisposable调用它。但这可能会导致死锁,因此我不建议您这样做。

相关文章