Понимание внутреннего устройства QuickGrid: «Отложить взлом»

Я изучаю исходный код QuickGrid от Blazor (ASP.NET Core 8) .Реализация использует некоторые внутренние знания о том, как Blazor обрабатывает фактическую отрисовку, чтобы собрать все дочерние компоненты ColumnBase. Это делается путем запуска и завершения «сеанса сбора», и во время этого сеанса все дочерние компоненты ColumnBase присоединяются к контексту каскадной сетки.

      <CascadingValue TValue="InternalGridContext<TGridItem>" IsFixed="true" Value="@_internalGridContext">
    @{ StartCollectingColumns(); }
    @ChildContent
    <Defer>
        @{ FinishCollectingColumns(); }
        <ColumnsCollectedNotifier TGridItem="TGridItem" />

        @* HTML table... *@
    </Defer>
</CascadingValue>

Компоненты ColumnBase внутри ChildContent выполняют следующий код в своем методе BuildRenderTree:

      InternalGridContext.Grid.AddColumn(this, InitialSortDirection, IsDefaultSortColumn);

Компонент Defer построен следующим образом:

      // This is used by QuickGrid to move its body rendering to the end of the render queue so we can collect
// the list of child columns first. It has to be public only because it's used from .razor logic.
public sealed class Defer : ComponentBase
{
    [Parameter] public RenderFragment? ChildContent { get; set; }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.AddContent(0, ChildContent);
    }
}

В компоненте Defer также есть комментарий, объясняющий, что он делает, и я это понимаю. Однако я не совсем понимаю, как и почему это работает. Может ли кто-нибудь объяснить мне подробности о том, как и почему это работает?

Это каким-то образом говорит о том, что RenderFragments задерживаются при рендеринге. Но для меня это не совсем интуитивно понятно. Я думаю о рендеринге как о своего рода обходе дерева левого порядка узлов, включая RenderFragments. Но похоже, что RenderFragments изначально не просматриваются.

2 ответа

Я думаю о рендеринге как о своего рода обходе дерева левого порядка узлов, включая RenderFragments.

На самом деле обход осуществляется не в глубину, а скорее в ширину. Дочерние компоненты создаются при рендеринге родительского компонента, и все они визуализируются после родительского компонента.

Но похоже, что RenderFragments изначально не просматриваются.

Речь идет не о RenderFragments, а о дочерних компонентах. Насколько я могу судить, истинная цель@{ FinishCollectingColumns(); }линия.
Без<Defer>на тот момент столбцы еще не были зарегистрированы. Поскольку столбцы были бы созданы, но ни один из них не был бы отображен и, следовательно, не было бы возможности вызватьAddColumn(this,).

Я предполагаю, что вы понимаете:

  1. Что такое на самом деле - делегат.
  2. Файлы Razor компилируются в классы C#.
  3. Эта разметка Razor компилируется в набор инструкций.

Когда рендерер проходит через сгенерированныйКод C#, который он создает, внедряет, прикрепляет и вызывает.для каждого компонента столбца по мере необходимости. В коде столбца не используется асинхронный код возврата, поэтому все происходит последовательно, включая укладку фрагментов рендеринга для каждого столбца в очереди рендеринга. Пользовательский интерфейс Blazor работает в контексте синхронизации , который обеспечивает один поток выполнения.

Таким образом, каждый компонент— Процесс регистрации — выполняется последовательно, и все регистрации завершаются до того, как мы доберемся до последнего компонента. Егопредоставляется.

Вы можете увидеть это, поместив фрагмент рендеринга, который фактически строит сетку, внутри подчиненного компонента —— вы откладываете рендеринг этого фрагмента до тех пор, пока процессы, от которых он зависит — регистрация столбцов — не будут завершены.

Вы можете использовать аналогичный процесс для других типов составных элементов управления.

Другие вопросы по тегам