pokročilé scénáře ASP.NET Core Blazor (vytváření stromové struktury)
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Tento článek popisuje pokročilý scénář pro ruční vytváření Blazor stromů vykreslování pomocí RenderTreeBuilder.
Upozorňující
RenderTreeBuilder Použití k vytvoření komponent je pokročilý scénář. Nedefinovaná komponenta (například nezařazená značka značek) může mít za následek nedefinované chování. Nedefinované chování zahrnuje poškozené vykreslování obsahu, ztrátu funkcí aplikace a ohrožení zabezpečení.
Ruční sestavení stromu vykreslování (RenderTreeBuilder
)
RenderTreeBuilder poskytuje metody pro manipulaci s komponentami a prvky, včetně ručního sestavování součástí v kódu jazyka C#.
Představte si následující PetDetails
komponentu, kterou lze ručně vykreslit v jiné komponentě.
PetDetails.razor
:
<h2>Pet Details</h2>
<p>@PetDetailsQuote</p>
@code
{
[Parameter]
public string? PetDetailsQuote { get; set; }
}
V následující BuiltContent
komponentě smyčka v CreateComponent
metodě generuje tři PetDetails
komponenty.
V RenderTreeBuilder metodách s pořadovým číslem jsou pořadová čísla řádky zdrojového kódu. Algoritmus Blazor rozdílu spoléhá na pořadová čísla odpovídající odlišným řádkům kódu, nikoli k odlišným voláním. Při vytváření komponenty s metodami RenderTreeBuilder pevně zakódujte argumenty pro pořadová čísla. Použití výpočtu nebo čítače ke generování pořadového čísla může vést k nízkému výkonu. Další informace najdete v části Pořadová čísla související s čísly řádků kódu, nikoli oddílem pořadí provádění.
BuiltContent.razor
:
@page "/built-content"
<PageTitle>Built Content</PageTitle>
<h1>Built Content Example</h1>
<div>
@CustomRender
</div>
<button @onclick="RenderComponent">
Create three Pet Details components
</button>
@code {
private RenderFragment? CustomRender { get; set; }
private RenderFragment CreateComponent() => builder =>
{
for (var i = 0; i < 3; i++)
{
builder.OpenComponent(0, typeof(PetDetails));
builder.AddAttribute(1, "PetDetailsQuote", "Someone's best friend!");
builder.CloseComponent();
}
};
private void RenderComponent() => CustomRender = CreateComponent();
}
@page "/built-content"
<PageTitle>Built Content</PageTitle>
<h1>Built Content Example</h1>
<div>
@CustomRender
</div>
<button @onclick="RenderComponent">
Create three Pet Details components
</button>
@code {
private RenderFragment? CustomRender { get; set; }
private RenderFragment CreateComponent() => builder =>
{
for (var i = 0; i < 3; i++)
{
builder.OpenComponent(0, typeof(PetDetails));
builder.AddAttribute(1, "PetDetailsQuote", "Someone's best friend!");
builder.CloseComponent();
}
};
private void RenderComponent() => CustomRender = CreateComponent();
}
@page "/built-content"
<h1>Build a component</h1>
<div>
@CustomRender
</div>
<button @onclick="RenderComponent">
Create three Pet Details components
</button>
@code {
private RenderFragment? CustomRender { get; set; }
private RenderFragment CreateComponent() => builder =>
{
for (var i = 0; i < 3; i++)
{
builder.OpenComponent(0, typeof(PetDetails));
builder.AddAttribute(1, "PetDetailsQuote", "Someone's best friend!");
builder.CloseComponent();
}
};
private void RenderComponent()
{
CustomRender = CreateComponent();
}
}
Upozorňující
Typy, které Microsoft.AspNetCore.Components.RenderTree umožňují zpracování výsledků operací vykreslování. Jedná se o interní podrobnosti implementace Blazor architektury. Tyto typy by se měly považovat za nestabilní a v budoucích verzích by se měly měnit.
Pořadová čísla souvisejí s čísly řádků kódu a ne pořadím provádění.
Razor soubory komponent (.razor
) se vždy kompilují. Spouštění zkompilovaného kódu má potenciální výhodu při interpretaci kódu, protože krok kompilace, který zkompilovaný kód přináší, lze použít k vložení informací, které zlepšují výkon aplikace za běhu.
Klíčovým příkladem těchto vylepšení jsou pořadová čísla. Pořadová čísla označují modul runtime, ze kterého výstupy pocházejí, z nichž různé a seřazené řádky kódu pocházejí. Modul runtime používá tyto informace ke generování efektivních rozdílů stromu v lineárním čase, což je mnohem rychlejší, než je obvykle možné pro obecný algoritmus rozdílu stromu.
Zvažte následující Razor soubor komponenty (.razor
):
@if (someFlag)
{
<text>First</text>
}
Second
Předchozí Razor kód a textový obsah se zkompiluje do kódu jazyka C#, který je podobný následujícímu:
if (someFlag)
{
builder.AddContent(0, "First");
}
builder.AddContent(1, "Second");
Při prvním spuštění kódu a someFlag
je true
, tvůrce obdrží posloupnost v následující tabulce.
Sequence | Typ | Data |
---|---|---|
0 | Textový uzel | První |
0 | Textový uzel | Second |
Představte si, že se someFlag
kód stane false
a znovu se vykreslí. Tentokrát tvůrce obdrží sekvenci v následující tabulce.
Sequence | Typ | Data |
---|---|---|
0 | Textový uzel | Second |
Když modul runtime provede rozdíl, zjistí, že položka v sekvenci 0
byla odebrána, takže vygeneruje následující triviální skript pro úpravy jedním krokem:
- Odeberte první textový uzel.
Problém se generováním pořadových čísel prostřednictvím kódu programu
Představte si místo toho, že jste napsali následující logiku tvůrce stromové struktury vykreslování:
var seq = 0;
if (someFlag)
{
builder.AddContent(seq++, "First");
}
builder.AddContent(seq++, "Second");
První výstup se odráží v následující tabulce.
Sequence | Typ | Data |
---|---|---|
0 | Textový uzel | První |
0 | Textový uzel | Second |
Tento výsledek je identický s předchozím případem, takže neexistují žádné negativní problémy. someFlag
je false
na druhém vykreslování a výstup se zobrazí v následující tabulce.
Sequence | Typ | Data |
---|---|---|
0 | Textový uzel | Second |
Tentokrát rozdílový algoritmus zjistí, že došlo ke dvěma změnám. Algoritmus vygeneruje následující skript pro úpravy:
- Změňte hodnotu prvního textového uzlu na
Second
. - Odeberte druhý textový uzel.
Generování pořadových čísel ztratilo všechny užitečné informace o tom, kde if/else
byly větve a smyčky přítomny v původním kódu. Výsledkem je rozdíl dvakrát tak dlouho jako předtím.
Toto je triviální příklad. V realističtějších případech se složitými a hluboce vnořenými strukturami, a zejména se smyčkami, jsou náklady na výkon obvykle vyšší. Místo okamžité identifikace bloků smyčky nebo větví, které byly vloženy nebo odebrány, musí algoritmus rozdílu hluboko zabrat do vykreslovaných stromů. To obvykle vede k vytvoření delších skriptů pro úpravy, protože algoritmus rozdílu je nesprávně informován o tom, jak staré a nové struktury vzájemně souvisejí.
Pokyny a závěry
- Výkon aplikace trpí tím, že se pořadová čísla generují dynamicky.
- Potřebné informace neexistují, aby architektura automaticky vygenerovala pořadová čísla za běhu, pokud se informace nezachytí v době kompilace.
- Nezapisujte dlouhé bloky ručně implementované RenderTreeBuilder logiky. Upřednostňujte
.razor
soubory a povolte kompilátoru pracovat s pořadovými čísly. Pokud se nemůžete vyhnout ruční RenderTreeBuilder logice, rozdělte dlouhé bloky kódu na menší části zabalené do OpenRegion/CloseRegion volání. Každá oblast má svůj vlastní samostatný prostor sekvenčních čísel, takže můžete restartovat z nuly (nebo jakéhokoli jiného libovolného čísla) v každé oblasti. - Pokud jsou pořadová čísla pevně zakódovaná, algoritmus rozdílu vyžaduje pouze zvýšení hodnoty pořadových čísel. Počáteční hodnota a mezery jsou irelevantní. Jednou z legitimních možností je použít číslo řádku kódu jako pořadové číslo nebo začít od nuly a zvýšit je o jednu nebo stovky (nebo libovolný upřednostňovaný interval).
- U smyček by se pořadová čísla měla zvýšit ve zdrojovém kódu, ne z hlediska chování modulu runtime. Skutečnost, že za běhu se čísla opakují, je způsob, jakým rozdílový systém uvědomuje, že jste ve smyčce.
- Blazor používá pořadová čísla, zatímco jiné architektury uživatelského rozhraní využívající stromové rozdíly je nepoužívají. Rozdíl je při použití pořadových čísel mnohem rychlejší a Blazor má výhodu kroku kompilace, který se automaticky zabývá pořadovými čísly pro vývojáře, kteří
.razor
vytváří soubory.