对于 Blazor 组件虚拟化支持flex-wrap: wrap与网格布局的研究 [三]
接上篇文章 对于 Blazor 组件虚拟化支持flex-wrap: wrap与网格布局的研究 [二]
本文源码
监控元素的宽度变化动态计算
为了监控 id="div-test" 元素的宽度变化,你可以使用 ResizeObserver API。以下是如何实现的步骤:
- 在 Routes.razor 或 _Host.cshtml 或 wwwroot/index.html 文件中添加一个 JavaScript 函数来监控元素的宽度变化:
<script>
window.observeElementWidth = (elementId, dotNetHelper) => {
const element = document.getElementById(elementId);
if (element) {
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
dotNetHelper.invokeMethodAsync('OnElementWidthChanged', entry.contentRect.width);
}
});
resizeObserver.observe(element);
}
};
</script>
- 在 Virtualized.razor 文件中,使用 JSRuntime 调用这个 JavaScript 函数,并在 OnElementWidthChanged 方法中处理宽度变化事件。
- 在 OnElementWidthChanged 方法中,更新 itemsPerRow 并重新分组订单,渲染页面
完整代码如下
<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);
//GroupOrders();
//StateHasChanged();
await JSRuntime.InvokeVoidAsync("observeElementWidth", "div-test", DotNetObjectReference.Create(this));
}
}
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)));
}
}
private void GroupOrders()
{
GroupedOrders = Orders
.Select((order, index) => new { order, index })
.GroupBy(x => x.index / itemsPerRow)
.Select(g => g.Select(x => x.order))
.ToList();
}
[JSInvokable]
public void OnElementWidthChanged(float newWidth)
{
elementWidth = newWidth;
itemsPerRow =(int) elementWidth / (itemsHeight + 20);
GroupOrders();
StateHasChanged();
}
}
后续
小问题处理一下, 页面切换后,OnElementWidthChanged 回报上来的宽度会变成0.
[JSInvokable]
public void OnElementWidthChanged(float newWidth)
{
if (newWidth == 0)
{
//页面切换后,OnElementWidthChanged 回报上来的宽度会变成0
return;
}
elementWidth = newWidth;
itemsPerRow = (int)elementWidth / (itemsHeight + 20);
GroupOrders();
StateHasChanged();
}
本文源码
关联项目
FreeSql QQ群:4336577
BA & Blazor QQ群:795206915
Maui Blazor 中文社区 QQ群:645660665
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。
转载声明
本文来自博客园,作者:周创琳 AlexChow,转载请注明原文链接:https://www.cnblogs.com/densen2014/p/18677530
AlexChow
今日头条 | 博客园 | 知乎 | Gitee | GitHub