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

Fra*_*nco 0 javascript css blazor

我想在剃刀页面中做这样的事情:

@if (currentwidth<x)
{
   le code
}
else
{
    le other code
}
Run Code Online (Sandbox Code Playgroud)

我添加了 javascript 文件并将其连接到一个实用程序服务,该服务在我获得静态宽度(我测试过)时起作用。

js:

export function getCurrentWidth() {

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

}
Run Code Online (Sandbox Code Playgroud)

实用服务方法:

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

剃刀文件:

double width;

    protected async override Task OnInitializedAsync()
    {
        width = await utilityService.GetCurrentWidth();
    }
Run Code Online (Sandbox Code Playgroud)

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

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

Nij*_*hof 6

首先,我想指出,您可能不必使用 javascript/C# 代码来解决您的问题。如果您想要操作 html 中的某些内容,那么使用 css 可能会更好。但我会把它留给你。

但是,如果您确实需要像上面提到的那样的窗口宽度,那么我建议向窗口注册一个侦听器(正如您已经完成的那样)并让该侦听器调用 dotnet 函数。使用静态方法执行此操作非常简单,但对于组件来说,这可能有点棘手,因为您必须传递当前对象的对象引用。

[JsInvokable] 表示可以从 javascript 调用此方法,这允许从 javascript 事件侦听器到 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

CSharpFromJs.razor

@implements IAsyncDisposable

<h1>Window width: @WindowWidth</h1>
Run Code Online (Sandbox Code Playgroud)

JavaScript

// 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);
}
Run Code Online (Sandbox Code Playgroud)

您唯一应该小心的是当组件被废弃时。您应该删除 DisposeAsync 函数中已注册的处理程序,以确保它们尚未注册以防止内存泄漏。

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

注意:这仅适用于 .net5 及更高版本,因为在此之前组件尚未实现 IAsyncDisposable。如果由于某种原因您使用的是早期版本,您可以使用 IDisposable 调用它。但这可能会导致死锁,所以我不推荐它。