#c# #blazor
Вопрос:
У меня есть компоненты Blazor, похожие на это:
Главная.бритва
@foreach (Vehicle vehicle in _vehicles)
{
if (vehicle.Visible)
{
<VehicleComponent Vehicle=@vehicle></VehicleComponent>
}
}
@code {
protected override void OnInitialized()
{
_vehicles = new List<Vehicles>();
// -> _vehicles being filled here
base.OnInitialized();
}
}
Компонент транспортного средства.бритва
@if (Vehicle != null)
{
<img src="@(Vehicle.src)"/>
<div id="@(Vehicle.Id)" tabindex="@(Vehicle.tabindex)">
<h3>@(Vehicle.text)</h3>
</div>
}
@code {
[Parameter] public Vehicle Vehicle { get; set; }
}
Проблема в том, что все VehicleComponent
s внутри цикла отображаются после завершения цикла. Но я хочу, чтобы компонент был полностью отрисован до того, как будет отрисован следующий элемент списка.
Я пробовал использовать StateHasChanged()
после каждого элемента Main.razor
, но получился бесконечный цикл. Есть ли способ, которым я могу отображать каждый компонент в цикле друг за другом (и обновлять пользовательский интерфейс)?
Комментарии:
1. Почему? [комментарий слишком короткий]
2. Это не причина для обновления пользовательского интерфейса внутри цикла. В любом случае, это не то, что делает опубликованный вами код. Если вы хотите, чтобы отдельные компоненты обновлялись при изменении свойства, свяжите это свойство с параметром компонентов. Это единственный способ, которым компонент может узнать, что, например
vehicle.Visible
, изменился3. Что касается
rendered after the loop is finished.
того, в чем заключается реальная проблема? Этот компонент прост и не должен занимать много времени для визуализации. Вы пытаетесь отобразить гораздо больше элементов, чем может быть отображено? Это плохая идея и вызовет серьезные проблемы с производительностью и прокруткой, независимо от структуры. Вместо этого используйте виртуализацию компонентов , чтобы отображать только видимые строки4. попробуйте использовать
@key=...
5. Если вы используете Virtualize, вы ДОЛЖНЫ убедиться, что элемент — заполнитель шаблона точно соответствует высоте отображаемого элемента списка-если элементы списка различаются по размеру, это не для вас.
Ответ №1:
Если вам нужен визуальный эффект «постепенно появляющихся» предметов:
protected override async Task OnInitializedAsync ()
{
var temp = new List<Vehicles>();
// -> _vehicles being filled here
_vehicles = new List<Vehicles>();
foreach (var vehicle in temp)
{
_vehicles.Add(vehicle);
StateHasChanged();
await task.Delay(500); // adjust the delay to taste
}
}
но имейте в виду, что это дорогой (медленный) способ показать их.
Использование @key
не улучшит ситуацию, но это может помочь, когда вы измените список позже:
<VehicleComponent @key=vehicle Vehicle=@vehicle></VehicleComponent>
Ответ №2:
Я думаю, что вы неправильно понимаете процесс рендеринга.
Ваш код Razor компилируется в класс C#, а ваш Razor компилируется как RenderFragment
(делегат) — вы можете увидеть это в obj/Debug/Net5
структуре папок проекта. События компонента «Визуализация» помещают этот делегат в очередь средства визуализации. Средство визуализации выполняет эти делегаты и применяет изменения к DOM средства визуализации. Любые изменения в DOM визуализатора передаются в браузер для изменения его DOM.
Ответ Хенка медленно добавляет элементы в список. Он добавляет событие «Рендеринга» StateHasChanged
, а затем выполняет Task.Delay
его, чтобы позволить визуализатору повторно отображать список на каждой итерации.