接上篇文章 Blazor 通过组件虚拟化提高性能
问题
我想使用虚拟化来呈现项目。我使用的是弹性布局,flex-wrap: wrap当宽度完全用完时,我会将这些项目包裹起来( )。第一个项目将按预期呈现(只要您没有触摸滚动条)。开始滚动时,所有项目都会闪烁,并且控件不再可用。
<PageTitle>Virtualized Orders</PageTitle>
<h1>Virtualized Orders</h1>
<div style="height: 600px; overflow-y: scroll; display: flex; width: 600px; flex-direction: row; flex-wrap: wrap; ">
<Virtualize Items="Orders" Context="order" OverscanCount="15">
<div style="width: 100px;height:100px; background-color:cadetblue;padding:10px; margin: 10px;">
<div>$ @order.Value</div>
</div>
</Virtualize>
</div>
@code {
public record Order(Guid Id, int Value);
public IList<Order> Orders { get; set; } = new List<Order>();
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)));
}
}
}
原因是这种方案不受支持。要了解支持哪些内容,您可以阅读 Blazor 虚拟化文档。
Virtualize
Virtualize在下列条件下工作:
-
所有呈现的内容项(包括占位符内容)的高度都相同。这样就可以计算出哪些内容对应于给定的滚动位置,而无需先获取每个数据项并将数据呈现到 DOM 元素中。
-
间隔行和内容行均呈现在单个垂直堆栈中,每个项目都填充整个水平宽度。在典型用例中,Virtualize与元素配合使用div。如果您使用 CSS 创建更高级的布局,请记住以下要求:
- 滚动容器样式需要display具有以下任意值:
- block( a 的默认值div)。
- table-row-group( a 的默认值tbody)。
- flexflex-direction设置为。column确保Virtualize
组件的直接子组件不会在 flex 规则下收缩。例如,添加.mycontainer > div { flex-shrink: 0 }。
- 内容行样式需要display具有以下任一值:
- block( a 的默认值div)。
- table-row( a 的默认值tr)。
- 不要使用 CSS 来干扰间隔元素的布局。间隔元素display的值为block,除非父元素是表格行组,在这种情况下它们的默认值为table-row。不要试图影响间隔元素的宽度或高度,包括让它们具有边框或content伪元素。
- 滚动容器样式需要display具有以下任意值:
任何阻止间隔物和内容元素呈现为单个垂直堆栈的方法,或导致内容项高度变化的方法,都会阻止Virtualize
深入
既然已经了解原理,那我们可不可以转换一下思路, 把元素分组渲染,每行渲染一批,这样高度不就是固定了吗?
分组代码
<PageTitle>Virtualized Orders</PageTitle>
<h1>Virtualized Orders</h1>
<div 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>
@code {
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; }
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();
}
}
后续
可以试封装成组件, 公开 itemsPerRow 和 itemsHeight 等参数, 配合查询父元素/屏幕宽度,就能自适应调节了.
标签:flex,元素,order,组件,wrap,new,Blazor,Orders From: https://www.cnblogs.com/densen2014/p/18677406