Maui Blazor 中文社区 QQ群:645660665

对于 Blazor 组件虚拟化支持flex-wrap: wrap与网格布局的研究 [二]

接上篇文章 对于 Blazor 组件虚拟化支持flex-wrap: wrap与网格布局的研究 [一]

本文源码

https://github.com/densen2014/Blazor100/blob/master/b24Virtualization/BlazorVirtualization/Pages/VirtualizedFlex2.razor

自适应

可以试封装成组件, 公开 itemsPerRow 和 itemsHeight 等参数, 配合查询父元素/屏幕宽度,就能自适应调节了.

在 Blazor 组件中使用 JavaScript 互操作来查询 id="div-test" 元素的渲染宽度。以下是如何实现的步骤:

  1. 在 Routes.razor 或 _Host.cshtml 或 wwwroot/index.html 文件中添加一个 JavaScript 函数来获取元素的宽度:
<script>
    window.getElementWidth = (elementId) => {
        const element = document.getElementById(elementId);
        return element ? element.offsetWidth : 0;
    };
</script>
  1. 在 Virtualized.razor 文件中使用 JSRuntime 调用这个 JavaScript 函数,并在 OnAfterRenderAsync 方法中获取元素的宽度。
@page "/"

<PageTitle>Virtualized Orders</PageTitle>

<h1>Virtualized Orders</h1>

<div id="div-test" style="height: 370px; overflow-y: scroll;  width: 380px; ">
    <Virtualize Items="GroupedOrders" Context="orderGroup" ItemSize="16.667f">
        <div style="display: flex; flex-direction: row; flex-wrap: wrap; ">
            @foreach (var order in orderGroup)
            {
                <div style="width: 100px; height: 100px; background-color: cadetblue; padding: 10px; margin: 10px;">
                    <div>$ @order.Value</div>
                </div>
            }
        </div>
    </Virtualize>
</div>

<p>元素宽度: @elementWidth px</p>

@code {
    private int elementWidth;

    int itemsPerRow = 3;

    public record Order(Guid Id, int Value);

    public IList<Order> Orders { get; set; } = new List<Order>();
    public IList<IEnumerable<Order>>? GroupedOrders { get; set; }

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

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            elementWidth = await JSRuntime.InvokeAsync<int>("getElementWidth", "div-test");
            StateHasChanged();
        }
    }

    protected override void OnInitialized()
    {
        var random = new Random();
        for (int i = 0; i < 100; i++)
        {
            Orders.Add(new Order(Guid.NewGuid(), random.Next(20, 9999)));
        }

        GroupedOrders = Orders
            .Select((order, index) => new { order, index })
            .GroupBy(x => x.index / itemsPerRow)
            .Select(g => g.Select(x => x.order))
            .ToList();
    }
}

加入自动计算

<div id="div-test" style="height: 370px; overflow-y: scroll;  width: 70vw; ">
    @if (GroupedOrders != null)
    {
        <Virtualize Items="GroupedOrders" Context="orderGroup">
            <div style="display: flex; flex-direction: row; flex-wrap: wrap; ">
                @foreach (var order in orderGroup)
                {
                    <div style="width: 100px; height: 100px; background-color: cadetblue; padding: 10px; margin: 10px;">
                        <div>$ @order.Value</div>
                    </div>
                }
            </div>
        </Virtualize>
    }
</div>

<p>元素宽度: @elementWidth px 每行分配 @itemsPerRow 个元素</p>

@code {
    private float elementWidth;


    int itemsPerRow = 3;
    int itemsHeight = 100;

    public record Order(Guid Id, int Value);

    public IList<Order> Orders { get; set; } = new List<Order>();
    public IList<IEnumerable<Order>>? GroupedOrders { get; set; }

    [Inject]
    [System.Diagnostics.CodeAnalysis.NotNull]
    private IJSRuntime? JSRuntime { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            elementWidth = await JSRuntime.InvokeAsync<int>("getElementWidth", "div-test");
            itemsPerRow = (int)elementWidth / (itemsHeight+20);

            GroupedOrders = Orders
                .Select((order, index) => new { order, index })
                .GroupBy(x => x.index / itemsPerRow)
                .Select(g => g.Select(x => x.order))
                .ToList();

            StateHasChanged();
        }
    }

    protected override void OnInitialized()
    {
        var random = new Random();
        for (int i = 0; i < 100; i++)
        {
            Orders.Add(new Order(Guid.NewGuid(), random.Next(20, 9999)));
        }

    }
}

监控元素的宽度变化动态计算

监控 id="div-test" 元素的宽度变化

对于 Blazor 组件虚拟化支持flex-wrap: wrap与网格布局的研究 [三]

本文源码

https://github.com/densen2014/Blazor100/blob/master/b24Virtualization/BlazorVirtualization/Pages/VirtualizedFlex2.razor

posted @ 2025-01-17 18:33  AlexChow  阅读(2443)  评论(0)    收藏  举报