RazorASP.NET Core Součásti
BlazorAplikace se sestaví pomocí Razor komponent. Komponenta je samostatná část uživatelského rozhraní s logikou zpracování umožňující dynamické chování. Komponenty je možné vnořovat, opakovaně používat, sdílet mezi projekty a používat v aplikacích MVC Razor a Pages.
Třídy komponent
Komponenty jsou implementovány pomocí kombinace kódu C# a HTML v Razor souborech součástí s .razor příponou souboru.
Razor Syntaxe
Komponenty používají Razor syntaxi. Komponenty, direktivy a atributy direktiv ve velké části Razor používají dvě funkce. Jedná se o vyhrazená klíčová slova s @ předponou , která se zobrazují v Razor kódu:
- Direktivy:Změna způsobu analýzy značek komponent nebo funkcí. Direktiva například určuje směrovatelnou komponentu se šablonou trasy a je k dispozici přímo požadavkem uživatele v prohlížeči na
@pagekonkrétní adrese URL. - Atributydirektivy: Změna způsobu analýzy elementu komponenty nebo funkcí. Například atribut
@binddirektivy pro<input>element váže data na hodnotu elementu.
Direktivy a atributy direktiv používané v komponentách jsou podrobněji vysvětleny v tomto článku a dalších článcích Blazor sady dokumentace. Obecné informace o Razor syntaxi najdete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core .
Názvy
Název komponenty musí začínět velkým písmenem:
ProductDetail.razorje platný.- Formát
productDetail.razorje neplatný.
Mezi Blazor běžné zásady vytváření názvů používané v dokumentaci Blazor patří:
- Cesty k souborům součástí používají velká a malá písmena jazyka Pascal † a zobrazují se před zobrazením příkladů kódu komponent. Cesty označují typická umístění složek. Například označuje, že komponenta má název souboru a nachází
Pages/ProductDetail.razorProductDetailse veProductDetail.razorPagessložce aplikace. - Cesty k souborům součástí pro směrovatelné komponenty odpovídají jejich adresám URL se spojovníky, které se zobrazují pro mezery mezi slovy v šabloně trasy komponenty. Například komponenta se šablonou trasy ( ) se požaduje v prohlížeči
ProductDetailna relativní adrese URL/product-detail@page "/product-detail"/product-detail.
†Velká písmena jazyka Pascal (velkým písmenem camel case) jsou konvence pojmenování bez mezer a interpunkce a s prvním písmenem každého slova velkým písmenem, včetně prvního slova.
Směrování
Směrování v Blazor se dosahuje poskytnutím šablony trasy pro každou přístupnou komponentu v aplikaci pomocí @page direktivy . Při Razor kompilaci souboru s direktivou je vygenerované třídě dán @page RouteAttribute určení šablony trasy. Za běhu směrovač vyhledá třídy komponent pomocí a vykreslí, která komponenta má šablonu trasy, která odpovídá RouteAttribute požadované adrese URL.
Následující HelloWorld komponenta používá šablonu trasy /hello-world . Vykreslená webová stránka pro komponentu je dosažena na relativní adrese URL /hello-world . Při místním spuštění aplikace s výchozím protokolem, hostitelem a portem se komponenta vyžádá Blazor HelloWorld v prohlížeči na adrese https://localhost:5001/hello-world . Komponenty, které vytvářejí webové stránky, se obvykle nacházejí ve složce , ale k umístění součástí, včetně vnořených složek, můžete použít Pages libovolnou složku.
Pages/HelloWorld.razor:
@page "/hello-world"
<h1>Hello World!</h1>
Předchozí komponenta se načte v prohlížeči bez ohledu na to, jestli komponentu přidáte do navigace v uživatelském /hello-world rozhraní aplikace. Volitelně můžete do komponenty přidat komponenty, aby se odkaz na komponentu objeví v navigaci aplikace založené na NavMenu uživatelském rozhraní.
Pro předchozí HelloWorld komponentu přidejte do NavLink součásti následující NavMenu komponentu. Přidejte komponentu do nové položky seznamu ( ) mezi značky NavLink <li>...</li> neuspořádaných seznamu ( <ul>...</ul> ).
Shared/NavMenu.razor:
<li class="nav-item px-3">
<NavLink class="nav-link" href="hello-world">
<span class="oi oi-list-rich" aria-hidden="true"></span> Hello World!
</NavLink>
</li>
Další informace, včetně popisů komponent NavLink a , najdete v tématu NavMenu ASP.NET Core Blazor úsek .
Kód
Uživatelské rozhraní komponenty je definováno pomocí Razor syntaxe, která se skládá z Razor kódu, jazyka C# a HTML. Při kompilaci aplikace se značky HTML a logika vykreslování v jazyce C# převedou do třídy komponent. Název vygenerované třídy odpovídá názvu souboru.
Členy třídy komponenty jsou definovány v jednom nebo více @code blocích. V @code blocích se stav komponenty specifikuje a zpracovává pomocí jazyka C#:
- Inicializátory vlastností a polí.
- Hodnoty parametrů z argumentů předané nadřazenými komponentami a parametry trasy.
- Metody pro zpracování událostí uživatele, události životního cyklu a logiku vlastních komponent
Členy komponent se používají v logice vykreslování pomocí výrazů jazyka C#, které začínají @ symbolem. Například pole jazyka C# se vykreslí @ předponou názvu pole. Následující Markup komponenta vyhodnotí a vykreslí:
headingFontStylejako hodnotu vlastnosti CSSfont-styleelementu heading.headingTextpro obsah elementu nadpisu.
Pages/Markup.razor:
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
Poznámka
Příklady v dokumentaci Blazor určují private modifikátor přístupu pro soukromé členy. Soukromé členy jsou vymezeny na třídu komponenty. Jazyk C# ale předpokládá modifikátor přístupu, když není k dispozici žádný modifikátor přístupu, takže explicitní označení členů ve vašem vlastním kódu private private je volitelné. Další informace o modifikátorech přístupu najdete v tématu Modifikátory přístupu (Průvodceprogramováním v C#).
Tato rozhraní interně zpracovává komponentu jako strom vykreslování , což je kombinace modelu Blazor model DOM (Document Object Model) (DOM) a CSSOM (Cascading Style Sheet Object Model). Po počátečním vykreslení komponenty se vykreslovací strom komponenty znovu vygeneruje v reakci na události. Blazor porovná nový strom vykreslování s předchozím stromem vykreslování a použije všechny úpravy modelu DOM prohlížeče k zobrazení. Další informace naleznete v tématu BlazorASP.NET Core vykreslování komponent.
Komponenty jsou běžné třídy jazyka C# a lze je umístit kdekoli v rámci projektu. Komponenty, které vytvářejí webové stránky, se obvykle nacházejí ve Pages složce . Ne stránkované komponenty jsou často umístěny ve složce nebo ve vlastní Shared složce přidané do projektu.
Vnořené komponenty
Komponenty mohou zahrnovat další komponenty deklarováním pomocí syntaxe HTML. Kód pro použití komponenty vypadá jako značka HTML, kde název značky je typ komponenty.
Vezměte v Heading úvahu následující komponentu, kterou mohou ostatní komponenty použít k zobrazení nadpisu.
Shared/Heading.razor:
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
Následující kód v HeadingExample komponentě vykreslí předchozí Heading komponentu v umístění, kde se <Heading /> značka nachází.
Pages/HeadingExample.razor:
@page "/heading-example"
<Heading />
Pokud komponenta obsahuje prvek HTML s velkým prvním písmenem, které neodpovídá názvu komponenty ve stejném oboru názvů, vysílá se upozornění, že má prvek neočekávaný název. Přidáním direktivy pro obor názvů komponenty je @using komponenta dostupná, což upozornění vyřeší. Další informace najdete v části Obory názvů.
Příklad komponenty zobrazený v této části nemá direktivu , takže komponenta není přímo přístupná uživateli prostřednictvím přímého požadavku Heading @page v Heading prohlížeči. Jakákoli komponenta s @page direktivou však může být vnořena do jiné součásti. Pokud by komponenta byla přímo přístupná zahrnutím do horní části souboru, vykreslí se komponenta pro požadavky prohlížeče na Heading @page "/heading" adrese i Razor /heading /heading-example .
Obory názvů
Obor názvů komponenty se obvykle odvozuje z kořenového oboru názvů aplikace a umístění komponenty (složky) v aplikaci. Pokud je kořenový obor názvů aplikace a BlazorSample Counter komponenta se nachází ve Pages složce :
- Obor
Counternázvů komponenty jeBlazorSample.Pages. - Plně kvalifikovaný název typu komponenty je
BlazorSample.Pages.Counter.
Pro vlastní složky, které mají součásti, přidejte direktivu do nadřazené komponenty nebo @using do souboru _Imports.razor aplikace. V následujícím příkladu jsou komponenty ve Components složce dostupné:
@using BlazorSample.Components
Poznámka
@using Direktivy v _Imports.razor souboru se použijí jenom na soubory ( ), nikoli na soubory Razor .razor jazyka C# ( .cs ).
Na komponenty lze také odkazovat pomocí plně kvalifikovaných názvů, což nevyžaduje @using direktivu . Následující příklad přímo odkazuje na ProductDetail komponentu Components ve složce aplikace:
<BlazorSample.Components.ProductDetail />
Obor názvů komponenty, pomocí které je autorován, je založen na Razor následujících vlastnostech (v pořadí podle priority):
- Direktiva
@namespacev kódu Razor souboru (například@namespace BlazorSample.CustomNamespace). - Projekt je v
RootNamespacesouboru projektu (například<RootNamespace>BlazorSample</RootNamespace>). - Název projektu převzatý z názvu souboru projektu ( ) a cestu z kořenového adresáře projektu
.csprojke komponentě. Například rozhraní se překládá{PROJECT ROOT}/Pages/Index.razors oborem názvů projektuBlazorSample( ) na obor názvů proBlazorSample.csprojBlazorSample.PagesIndexkomponentu.{PROJECT ROOT}je kořenová cesta projektu. Komponenty dodržují pravidla vazby názvů jazyka C#. Součástí v tomto příkladu jsou všechny součásti vIndexoboru:- Ve stejné složce:
Pages. - Komponenty v kořenovém adresáři projektu, které explicitně nezadá jiný obor názvů.
- Ve stejné složce:
Následující možnosti se nepodporují:
global::Kvalifikace.- Import komponent s příkazy s aliasem
using. Například@using Foo = Barnení podporován. - Částečně kvalifikované názvy. Například nemůžete přidat
@using BlazorSampledo komponenty a pak odkazovat naNavMenukomponentu veSharedsložce aplikace (Shared/NavMenu.razor) s<Shared.NavMenu></Shared.NavMenu>.
Podpora částečné třídy
Komponenty jsou generovány jako částečné třídy jazyka C# a jsou vytvořeny pomocí některého z následujících přístupů:
- Jeden soubor obsahuje kód C# definovaný v jednom nebo více
@codeblocích, značka HTML a Razor značky. Blazor šablony projektů definují své komponenty pomocí tohoto přístupu s jedním souborem. - HTML a Razor značky jsou umístěny v Razor souboru (
.razor). Kód jazyka C# je umístěn v souboru kódu na pozadí, který je definován jako částečná třída (.cs).
Poznámka
Šablona stylů komponenty, která definuje styly specifické pro komponentu, je samostatný soubor ( .css ). Blazor Izolace šablon stylů CSS je popsána dále v tématu ASP.NET Core Blazor Izolace šablon stylů CSS .
Následující příklad ukazuje výchozí Counter komponentu s @code blokem v aplikaci vygenerovanou Blazor šablonou projektu. Značky a kód jazyka C# jsou ve stejném souboru. Toto je nejběžnější přístup při vytváření součástí.
Pages/Counter.razor:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Následující Counter Komponenta rozdělí kód HTML a Razor značku z kódu jazyka C# pomocí souboru kódu na pozadí s částečnou třídou:
Pages/CounterPartialClass.razor:
@page "/counter-partial-class"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
Pages/CounterPartialClass.razor.cs:
namespace BlazorSample.Pages
{
public partial class CounterPartialClass
{
private int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
}
}
@using direktivy v _Imports.razor souboru jsou aplikovány pouze na Razor soubory ( .razor ), nikoli soubory jazyka C# ( .cs ). Podle potřeby přidejte do souboru dílčí třídy obory názvů.
Typické obory názvů používané součástmi:
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
Typické obory názvů také zahrnují obor názvů aplikace a obor názvů odpovídající Shared složce aplikace:
using BlazorSample;
using BlazorSample.Shared;
Zadat základní třídu
@inheritsDirektiva slouží k určení základní třídy pro komponentu. Následující příklad ukazuje, jak může komponenta zdědit základní třídu pro poskytnutí vlastností a metod komponenty. BlazorRocksBaseZákladní třída je odvozena z ComponentBase .
Pages/BlazorRocks.razor:
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
BlazorRocksBase.cs:
using Microsoft.AspNetCore.Components;
namespace BlazorSample
{
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
}
Parametry součásti
Parametry komponenty přecházejí data na součásti a jsou definovány pomocí vlastností Public jazyka C# třídy Component s [Parameter] atributem. V následujícím příkladu je vestavěný odkazový typ ( System.String ) a uživatelsky definovaný typ odkazu ( PanelBody ) předány jako parametry součásti.
PanelBody.cs:
public class PanelBody
{
public string? Text { get; set; }
public string? Style { get; set; }
}
Shared/ParameterChild.razor:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">@Title</div>
<div class="card-body" style="font-style:@Body.Style">
@Body.Text
</div>
</div>
@code {
[Parameter]
public string Title { get; set; } = "Set By Child";
[Parameter]
public PanelBody Body { get; set; } =
new()
{
Text = "Set by child.",
Style = "normal"
};
}
Upozornění
Poskytování počátečních hodnot pro parametry součásti je podporováno, ale nevytvářejte komponentu, která zapisuje do vlastních parametrů po prvním vygenerování součásti. Další informace najdete v části přepsané parametry tohoto článku.
Title Body Parametry komponenty a ParameterChild komponenty jsou nastaveny podle ARGUMENTŮ ve značce HTML, která vykresluje instanci komponenty. Následující ParameterParent Komponenta vykreslí dvě ParameterChild komponenty:
- První
ParameterChildKomponenta je vykreslena bez nutnosti zadávat argumenty parametru. - Druhá
ParameterChildKomponenta přijímá hodnoty proTitleaBodyzeParameterParentsoučásti, která používá explicitní výraz jazyka C# k nastavení hodnotPanelBodyvlastností.
Pages/ParameterParent.razor:
@page "/parameter-parent"
<h1>Child component (without attribute values)</h1>
<ParameterChild />
<h1>Child component (with attribute values)</h1>
<ParameterChild Title="Set by Parent"
Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />
Následující vykreslený kód HTML ze ParameterParent součásti zobrazuje ParameterChild výchozí hodnoty komponent, pokud ParameterParent Komponenta neposkytuje hodnoty parametrů komponenty. Pokud ParameterParent Komponenta poskytuje hodnoty parametrů komponenty, nahradí ParameterChild výchozí hodnoty součásti.
Poznámka
Pro přehlednost nejsou vykreslené třídy stylu CSS zobrazeny v následujícím vykresleném kódu HTML.
<h1>Child component (without attribute values)</h1>
<div>
<div>Set By Child</div>
<div>Set by child.</div>
</div>
<h1>Child component (with attribute values)</h1>
<div>
<div>Set by Parent</div>
<div>Set by parent.</div>
</div>
Přiřaďte pole, vlastnost nebo výsledek metody v jazyce C# k parametru komponenty jako hodnotu atributu HTML pomocí Razor rezervovaného @ symbolu. Následující ParameterParent2 Komponenta zobrazí čtyři instance předchozí ParameterChild komponenty a nastaví jejich Title hodnoty parametrů na:
- Hodnota
titlepole - Výsledek
GetTitlemetody jazyka C#. - Aktuální místní datum v dlouhém formátu s ToLongDateString , které používá implicitní výraz jazyka C#.
panelDataTitleVlastnost objektu.
Pages/ParameterParent2.razor:
@page "/parameter-parent-2"
<ParameterChild Title="@title" />
<ParameterChild Title="@GetTitle()" />
<ParameterChild Title="@DateTime.Now.ToLongDateString()" />
<ParameterChild Title="@panelData.Title" />
@code {
private string title = "From Parent field";
private PanelData panelData = new();
private string GetTitle()
{
return "From Parent method";
}
private class PanelData
{
public string Title { get; set; } = "From Parent object";
}
}
Poznámka
Při přiřazování člena v jazyce C# k parametru komponenty, předponu člena se @ symbolem a nikdy neprefixujte atribut HTML parametru.
Správná odpověď.
<ParameterChild Title="@title" />
Nesprávná odpověď:
<ParameterChild @Title="title" />
Na rozdíl od na Razor stránkách ( .cshtml ) Blazor nemůže při vykreslování komponenty provádět asynchronní práci ve Razor výrazu. Důvodem je to Blazor , že je určený pro vykreslování interaktivních uživatelská rozhraní. V interaktivním uživatelském rozhraní musí obrazovka vždycky zobrazit něco, takže nemá smysl zablokovat tok vykreslování. Místo toho se provádí asynchronní práce během jedné z asynchronních událostí životního cyklu. Po každé asynchronní události životního cyklu se komponenta může znovu vykreslit. Následující Razor syntaxe není podporována :
<ParameterChild Title="@await ..." />
Kód v předchozím příkladu generuje při sestavení aplikace chybu kompilátoru :
Operátor await jde použít jenom v asynchronní metodě. Zvažte označení této metody pomocí modifikátoru Async a změnu jejího návratového typu na Task.
Chcete-li získat hodnotu Title parametru v předchozím příkladu asynchronně, komponenta může použít OnInitializedAsync událost životního cyklu, jak ukazuje následující příklad:
<ParameterChild Title="@title" />
@code {
private string title;
protected override async Task OnInitializedAsync()
{
title = await ...;
}
}
Další informace naleznete v tématu RazorASP.NET Core životní cyklus komponenty.
Použití explicitního Razor výrazu k zřetězení textu s výsledkem výrazu pro přiřazení k parametru není podporováno. Následující příklad hledá zřetězení textu " Set by " s hodnotou vlastnosti objektu. I když je tato syntaxe podporována na Razor stránce ( .cshtml ), není platná pro přiřazení k Title parametru dítěte v součásti. Následující Razor syntaxe není podporována :
<ParameterChild Title="Set by @(panelData.Title)" />
Kód v předchozím příkladu generuje při sestavení aplikace chybu kompilátoru :
Atributy komponenty nepodporují složitý obsah (smíšený jazyk C# a označení).
Pro podporu přiřazení složené hodnoty použijte metodu, pole nebo vlastnost. Následující příklad provádí zřetězení " Set by " a hodnotu vlastnosti objektu v metodě jazyka C# GetTitle :
Pages/ParameterParent3.razor:
@page "/parameter-parent-3"
<ParameterChild Title="@GetTitle()" />
@code {
private PanelData panelData = new();
private string GetTitle() => $"Set by {panelData.Title}";
private class PanelData
{
public string Title { get; set; } = "Parent";
}
}
Další informace naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core.
Upozornění
Poskytování počátečních hodnot pro parametry součásti je podporováno, ale nevytvářejte komponentu, která zapisuje do vlastních parametrů po prvním vygenerování součásti. Další informace najdete v části přepsané parametry tohoto článku.
Parametry součásti by měly být deklarovány jako Automatické vlastnosti, což znamená, že by neměly obsahovat vlastní logiku ve svých get nebo přístupových sestavách set . Například následující StartData vlastnost je automatická vlastnost:
[Parameter]
public DateTime StartData { get; set; }
Neumísťujte vlastní logiku do get set přístupového objektu nebo, protože parametry komponenty jsou čistě určené pro použití jako kanál pro nadřazenou komponentu pro tok informací pro podřízenou komponentu. Pokud set přístupový objekt vlastnosti podřízené komponenty obsahuje logiku, která způsobí převykreslování nadřazené komponenty, výsledky smyčky nekonečného vykreslování.
Transformace přijaté hodnoty parametru:
- Ponechte vlastnost parametru jako automatickou vlastnost, která bude reprezentovat dodaná nezpracovaná data.
- Vytvořte jinou vlastnost nebo metodu pro poskytnutí transformovaných dat na základě vlastnosti parametru.
Přepište OnParametersSetAsync pro transformaci přijatého parametru pokaždé, když se přijímají nová data.
Zápis počáteční hodnoty do parametru komponenty je podporován, protože přiřazení počátečních hodnot nekoliduje s Blazor automatickým vykreslováním komponent. Následující přiřazení aktuální místní proměnné DateTime with DateTime.Now StartData je platnou syntaxí v součásti:
[Parameter]
public DateTime StartData { get; set; } = DateTime.Now;
Po počátečním přiřazení DateTime.Now nepřiřazujte hodnotu StartData v kódu pro vývojáře. Další informace najdete v části přepsané parametry tohoto článku.
Použijte [EditorRequired] atribut k určení požadovaného parametru součásti. Pokud není zadána hodnota parametru, mohou se editory nebo nástroje sestavení zobrazovat uživateli upozornění. Tento atribut je platný pouze pro vlastnosti, které jsou označeny [Parameter] atributem. EditorRequiredAttributeJe vynutila v době návrhu a při sestavení aplikace. Atribut se nevynutil za běhu a nezaručí null hodnotu, která není parametrem.
[Parameter]
[EditorRequired]
public string Title { get; set; }
Podporují se také seznamy s jedním řádkem atributů:
[Parameter, EditorRequired]
public string Title { get; set; }
Parametry směrování
Komponenty mohou určovat parametry směrování v šabloně směrování @page direktivy. Blazor Směrovač používá parametry směrování k naplnění odpovídajících parametrů komponent.
Volitelné parametry směrování jsou podporovány. V následujícím příkladu text volitelné parametr přiřadí hodnotu segmentu směrování do Text Vlastnosti komponenty. Pokud segment není k dispozici, hodnota Text je nastavena na hodnotu " fantastic " v OnInitialized metodě životního cyklu.
Pages/RouteParameter.razor:
@page "/route-parameter/{text?}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string? Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
Informace o zachycování všech parametrů tras ( {*pageRoute} ), které zachycují cesty mezi více hranicemi složek, naleznete v tématu ASP.NET Core Blazor úsek .
Přepsatelné parametry
BlazorRozhraní obecně ukládá bezpečné přiřazení parametrů z nadřazené na podřízený:
- Parametry nejsou neočekávaně přepsány.
- Vedlejší účinky jsou minimalizovány. Například další vykreslování se vyhne, protože mohou vytvářet nekonečné smyčky vykreslování.
Podřízená komponenta přijímá nové hodnoty parametrů, které mohou přepsat existující hodnoty při novém vykreslení nadřazené komponenty. Náhodné přepsání hodnot parametrů v podřízené komponentě se často objevuje při vývoji komponenty s jedním nebo více parametry svázanými s daty a vývojář přímo do parametru v podřízeném objektu:
- Podřízená komponenta je vykreslena s jednou nebo více hodnotami parametrů z nadřazené komponenty.
- Podřízený objekt zapisuje přímo na hodnotu parametru.
- Nadřazená komponenta přepíše hodnotu podřízeného parametru a přepíše ji.
Potenciál přepsání hodnot parametrů se vztahuje i na přístupové objekty vlastností podřízené set komponenty.
Důležité
Naším obecným pokynem není vytvářet komponenty, které po prvním vykreslení komponenty přímo zapisují do vlastních parametrů.
Vezměte v úvahu následující Expander vadnou komponentu, která:
- Vykreslí podřízený obsah.
- Přepínače zobrazující podřízený obsah s parametrem komponenty (
Expanded). - Komponenta zapisuje přímo do parametru , který ukazuje problém s přepsané parametry a je třeba
Expandedse jim vyhnout.
Jakmile následující komponenta předvede nesprávný přístup pro tento scénář, zobrazí se upravená komponenta, která Expander Expander demonstruje správný přístup. Následující příklady můžete umístit do místní ukázkové aplikace, abyste si mohli prohlédněte popsané chování.
Shared/Expander.razor:
<div @onclick="Toggle" class="card bg-light mb-3" style="width:30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code>Expanded</code> = @Expanded)</h2>
@if (Expanded)
{
<p class="card-text">@ChildContent</p>
}
</div>
</div>
@code {
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
private void Toggle()
{
Expanded = !Expanded;
}
}
Komponenta Expander se přidá do následující nadřazené ExpanderExample komponenty, která může volat StateHasChanged :
- Volání v kódu vývojáře upozorní komponentu na to, že se změnil její stav, a obvykle aktivuje opětovné vykreslení komponenty pro StateHasChanged aktualizaci uživatelského rozhraní. StateHasChanged je podrobněji popsán později v a RazorASP.NET Core životní cyklus komponenty BlazorASP.NET Core vykreslování komponent .
- Atribut direktivy
@onclicktlačítka připojí obslužnou rutinu události k událostionclicktlačítka. Zpracování událostí je podrobněji popsáno dále v ASP.NET Core Blazor zpracování událostí .
Pages/ExpanderExample.razor:
@page "/expander-example"
<Expander Expanded="true">
Expander 1 content
</Expander>
<Expander Expanded="true" />
<button @onclick="StateHasChanged">
Call StateHasChanged
</button>
Komponenty se zpočátku Expander chovají nezávisle při Expanded přepínání jejich vlastností. Podřízené komponenty udržují své stavy podle očekávání. Při volání v nadřazené komponentě se parametr první podřízené StateHasChanged Expanded komponenty resetuje zpět na počáteční hodnotu ( true ). Hodnota druhé Expander komponenty se resetuje, protože v druhé komponentě se nevykreslí žádný Expanded podřízený obsah.
Chcete-li zachovat stav v předchozím scénáři, použijte privátní pole v komponentě k Expander zachování přepínacího stavu.
Následující revidovaná Expander komponenta:
- Přijímá hodnotu
Expandedparametru komponenty z nadřazeného objektu. - Přiřadí hodnotu parametru komponenty privátního pole (
expanded) vOnInitializedudálosti. - Používá soukromé pole k zachování svého interního stavu přepínače, který ukazuje, jak se vyhnout přímému zápisu do parametru.
Poznámka
Rady v této části se vztahují na podobnou logiku v přistupování parametrů komponent, což může mít za následek set podobné nežádoucí vedlejší účinky.
Shared/Expander.razor:
<div @onclick="Toggle" class="card bg-light mb-3" style="width:30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code>expanded</code> = @expanded)</h2>
@if (expanded)
{
<p class="card-text">@ChildContent</p>
}
</div>
</div>
@code {
private bool expanded;
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
protected override void OnInitialized()
{
expanded = Expanded;
}
private void Toggle()
{
expanded = !expanded;
}
}
Příklady dvousměnných vazeb nadřazený-podřízený najdete v tématu BlazorASP.NET Core datová vazba . Další informace najdete v tématu Blazor Chyba dvousměnné vazby (dotnet/aspnetcore č. 24599).
Podřízený obsah
Komponenty mohou nastavit obsah jiné komponenty. Přiřazující komponenta poskytuje obsah mezi počátečními a uzavíracími značkami podřízené komponenty.
V následujícím příkladu má komponenta vlastnost, která představuje segment uživatelského rozhraní, RenderFragmentChild ChildContent který se má vykreslit jako RenderFragment . Pozice v kódu komponenty je místo, ChildContent kde se obsah vykresluje v konečném výstupu Razor HTML.
Shared/RenderFragmentChild.razor:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Child content</div>
<div class="card-body">@ChildContent</div>
</div>
@code {
[Parameter]
public RenderFragment? ChildContent { get; set; }
}
Důležité
Vlastnost přijímající obsah RenderFragment musí být pojmenována podle ChildContent konvence.
Následující komponenta poskytuje obsah pro vykreslení umístěním obsahu do počátečních a uzavíracích RenderFragmentParent RenderFragmentChild značek podřízené komponenty.
Pages/RenderFragmentParent.razor:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
Vzhledem ke způsobu, jakým vykresluje podřízený obsah, vyžaduje vykreslování součástí uvnitř smyčky místní proměnnou indexu, pokud se proměnná přírůstkové smyčky používá v Blazor for obsahu RenderFragmentChild komponenty. Následující příklad lze přidat k předchozí RenderFragmentParent komponentě:
<h1>Three children with an index variable</h1>
@for (int c = 0; c < 3; c++)
{
var current = c;
<RenderFragmentChild>
Count: @current
</RenderFragmentChild>
}
Alternativně můžete místo smyčky použít foreach Enumerable.Range for smyčku s . Následující příklad lze přidat k předchozí RenderFragmentParent komponentě:
<h1>Second example of three children with an index variable</h1>
@foreach (var c in Enumerable.Range(0,3))
{
<RenderFragmentChild>
Count: @c
</RenderFragmentChild>
}
Informace o tom, jak lze použít jako šablonu pro uživatelské rozhraní RenderFragment komponent, najdete v následujících článcích:
Sesoučování atributů a libovolné parametry
Komponenty mohou kromě deklarovaných parametrů komponenty zachytit a vykreslit další atributy. Další atributy mohou být zachyceny ve slovníku a poté při vykreslení komponenty pomocí @attributes Razor atributu direktivy přidány na prvek. Tento scénář je užitečný při definování komponenty, která vytváří prvek značek, který podporuje různá přizpůsobení. Například může být zdlouhavé definovat atributy samostatně pro objekt , <input> který podporuje mnoho parametrů.
V následující Splat komponentě:
- První prvek
<input>( ) používá parametry jednotlivýchid="useIndividualParams"součástí. - Druhý
<input>prvek (id="useAttributesDict") používá rozdělení atributů.
Pages/Splat.razor:
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
Vykreslené prvky <input> na webové stránce jsou identické:
<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
Pokud chcete přijímat libovolné atributy, definujte parametr komponenty s CaptureUnmatchedValues vlastností nastavenou na true :
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> InputAttributes { get; set; }
}
Vlastnost CaptureUnmatchedValues [Parameter] parametru umožňuje, aby odpovídal všem atributům, které neodpovídají žádnému jinému parametru. Komponenta může definovat pouze jeden parametr pomocí CaptureUnmatchedValues . Typ vlastnosti použitý s musí CaptureUnmatchedValues být možné přiřadit z pomocí Dictionary<string, object> řetězcových klíčů. V tomto IEnumerable<KeyValuePair<string, object>> IReadOnlyDictionary<string, object> scénáři je také možné použít nebo .
Pozice relativní @attributes vzhledem k pozici atributů elementu je důležitá. Při vytváření splatted elementu se atributy zpracovávají zprava @attributes doleva (od posledního k prvnímu). Představte si následující příklad nadřazené komponenty, která spotřebovává podřízené komponenty:
Shared/AttributeOrderChild1.razor:
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
Pages/AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
Atribut AttributeOrderChild1 komponenty extra je nastavený napravo od @attributes . Vykreslená komponenta obsahuje , pokud je předána prostřednictvím dalšího atributu, protože atributy jsou zpracovány zprava doleva AttributeOrderParent1 <div> extra="5" (od posledního k prvnímu):
<div extra="5" />
V následujícím příkladu je pořadí a v podřízené komponentě extra @attributes <div> obrácené:
Shared/AttributeOrderChild2.razor:
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
Pages/AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
v vykreslené webové stránce nadřazené komponenty <div> obsahuje , pokud je extra="10" předána prostřednictvím dalšího atributu:
<div extra="10" />
Zachycení odkazů na komponenty
Odkazy na komponenty poskytují způsob, jak odkazovat na instanci komponenty pro vydávání příkazů. Zachycení odkazu na komponentu:
- Přidejte
@refatribut do podřízené komponenty. - Definujte pole se stejným typem jako podřízený komponenta.
Po vykreslení komponenty se do pole vyplní instance komponenty. Pak můžete v instanci vyvolat metody .NET.
Vezměte v úvahu ReferenceChild následující komponentu, která při volání ChildMethod protokoluje zprávu.
Shared/ReferenceChild.razor:
@using Microsoft.Extensions.Logging
@inject ILogger<ReferenceChild> logger
@code {
public void ChildMethod(int value)
{
logger.LogInformation("Received {Value} in ChildMethod", value);
}
}
Odkaz na komponentu se naplní až po vykreslení komponenty a její výstup obsahuje ReferenceChild element . Dokud se komponenta nevykreslí, není nic, na co odkazovat.
Pokud chcete manipulovat s odkazy na komponenty po dokončení vykreslování komponenty, použijte OnAfterRender OnAfterRenderAsync metody nebo.
Pokud chcete použít referenční proměnnou s obslužnou rutinou události, použijte výraz lambda nebo přiřaďte delegáta obslužné rutiny události v OnAfterRender metodách OnAfterRenderAsync nebo. Tím se zajistí přiřazení referenční proměnné před přiřazením obslužné rutiny události.
Následující přístup lambda používá předchozí ReferenceChild komponentu.
Pages/ReferenceParent1.razor:
@page "/reference-parent-1"
<button @onclick="@(() => childComponent?.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild? childComponent;
}
Následující přístup delegáta používá předchozí ReferenceChild komponentu.
Pages/ReferenceParent2.razor:
@page "/reference-parent-2"
<button @onclick="@(() => callChildMethod?.Invoke())">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild? childComponent;
private Action? callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent?.ChildMethod(5);
}
}
Pomocí kolekce můžete odkazovat na komponenty ve smyčce. V následujícím příkladu:
- Součásti se přidávají do List<T> .
- Pro každou komponentu se vytvoří tlačítko, které aktivuje odpovídající komponentu podle
ChildMethodindexu její komponenty v List<T> .
Pages/ReferenceParent3.razor pomocí předchozí ReferenceChild komponenty:
@page "/reference-parent-3"
<ul>
@for (int i = 0; i < 5; i++)
{
var index = i;
var v = r.Next(1000);
<li>
<ReferenceChild @ref="childComponent" />
<button @onclick="@(() => callChildMethod?.Invoke(index, v))">
Component index @index: Call <code>ReferenceChild.ChildMethod(@v)</code>
</button>
</li>
}
</ul>
@code {
private Random r = new();
private List<ReferenceChild> components = new();
private Action<int, int>? callChildMethod;
private ReferenceChild childComponent
{
set => components.Add(value);
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod(int index, int value)
{
components.ElementAt(index).ChildMethod(value);
}
}
I když zachytávání odkazů na komponenty používá podobnou syntaxi pro zachytávání odkazů na elementy, zachytávání odkazů na komponenty není funkce zprostředkovatele komunikace JavaScriptu. Odkazy na komponenty se do javascriptového kódu předá. Odkazy na komponenty se používají pouze v kódu .NET.
Důležité
Nepoužívejte odkazy na komponenty k zmutování stavu podřízených komponent. Místo toho použijte normální parametry deklarativní komponenty k předání dat podřízeným komponentách. Použití parametrů komponenty má za následek automatické opětovné vykreslení podřízených komponent ve správných časech. Další informace najdete v části Parametry součásti a v BlazorASP.NET Core datová vazba článku.
Kontext synchronizace
Blazor používá kontext synchronizace ( SynchronizationContext ) k vynucení jednoho logického vlákna provádění. Metody životního cyklu komponenty a zpětná volání událostí vyvolaná pomocí se provádějí v Blazor kontextu synchronizace.
Blazor Serverse synchronizační kontext pokusí emulovat prostředí s jedním vláknem tak, aby přesně odpovídalo modelu WebAssembly v prohlížeči, což je jedno vlákno. V jakémkoli časovém okamžiku se práce provádí na právě jednom vlákně, což dává dojem jednoho logického vlákna. Žádné dvě operace se neskutou souběžně.
Vyhněte se voláním blokujícím vlákna
V komponentách obecně nevolejte následující metody. Následující metody blokují vlákno spuštění a zablokují tak aplikaci obnovení práce, dokud se Task nedokončí základní metoda:
Poznámka
Blazor Příklady dokumentace, které používají metody blokování vláken uvedené v této části, používají pouze metody pro demonstrační účely, nikoli jako doporučené pokyny ke kódování. Například několik ukázek kódu komponenty simuluje dlouhotrující proces voláním Thread.Sleep .
Externí vyvolání metod komponent pro aktualizaci stavu
V případě, že je nutné aktualizovat komponentu na základě externí události, jako je časovač nebo jiné oznámení, použijte metodu , která odesílá spuštění kódu do kontextu InvokeAsync Blazor synchronizace . Představte si například následující službu notifikátoru, která může upozornit jakoukoli komponentu naslouchání na aktualizovaný stav. Metodu Update je možné volat z libovolného místa v aplikaci.
TimerService.cs:
using System;
using Microsoft.Extensions.Logging;
public class TimerService : IDisposable
{
private int elapsedCount;
private readonly ILogger<TimerService> logger;
private readonly NotifierService notifier;
private System.Timers.Timer? timer;
public TimerService(NotifierService notifier,
ILogger<TimerService> logger)
{
this.notifier = notifier;
this.logger = logger;
}
public void Start()
{
if (timer is null)
{
timer = new();
timer.AutoReset = true;
timer.Interval = 10000;
timer.Elapsed += HandleTimer;
timer.Enabled = true;
logger.LogInformation("Started");
}
}
private async void HandleTimer(object? source,
System.Timers.ElapsedEventArgs e)
{
elapsedCount += 1;
await notifier.Update("elapsedCount", elapsedCount);
logger.LogInformation($"elapsedCount: {elapsedCount}");
}
public void Dispose()
{
timer?.Dispose();
}
}
NotifierService.cs:
using System;
using System.Threading.Tasks;
public class NotifierService
{
public async Task Update(string key, int value)
{
if (Notify != null)
{
await Notify.Invoke(key, value);
}
}
public event Func<string, int, Task>? Notify;
}
Zaregistrujte služby:
V aplikaci Blazor WebAssembly zaregistrujte služby jako singleton v
Program.cs:builder.Services.AddSingleton<NotifierService>(); builder.Services.AddSingleton<TimerService>();V aplikaci Blazor Server zaregistrujte služby jako vymezené v
Program.cs:builder.Services.AddScoped<NotifierService>(); builder.Services.AddScoped<TimerService>();
K NotifierService aktualizaci komponenty použijte .
Pages/ReceiveNotifications.razor:
@page "/receive-notifications"
@implements IDisposable
@inject NotifierService Notifier
@inject TimerService Timer
<h1>Receive Notifications</h1>
<h2>Timer Service</h2>
<button @onclick="StartTimer">Start Timer</button>
<h2>Notifications</h2>
<p>
Status:
@if (lastNotification.key is not null)
{
<span>@lastNotification.key = @lastNotification.value</span>
}
else
{
<span>Awaiting first notification</span>
}
</p>
@code {
private (string key, int value) lastNotification;
protected override void OnInitialized()
{
Notifier.Notify += OnNotify;
}
public async Task OnNotify(string key, int value)
{
await InvokeAsync(() =>
{
lastNotification = (key, value);
StateHasChanged();
});
}
private void StartTimer()
{
Timer.Start();
}
public void Dispose()
{
Notifier.Notify -= OnNotify;
}
}
V předchozím příkladu:
NotifierServicevyvolá metodu komponentyOnNotifymimo Blazor synchronizační kontext .InvokeAsyncslouží k přepnutí na správný kontext a zařadit vykreslování do fronty. Další informace naleznete v tématu BlazorASP.NET Core vykreslování komponent.- Komponenta implementuje IDisposable . Delegát
OnNotifyje odhlásí vDisposemetodě , která je volána rozhraním při uvolnění komponenty. Další informace naleznete v tématu RazorASP.NET Core životní cyklus komponenty.
Slouží @key k řízení zachování prvků a komponent.
Při vykreslování seznamu prvků nebo komponent a následně se prvky nebo komponenty změní, musí se rozhodnout, které z předchozích prvků nebo komponent lze zachovat a jak by se na ně objekty modelu Blazor měly mapovat. Za normálních okolností je tento proces automatický a je možné ho ignorovat, ale existují případy, kdy můžete chtít proces řídit.
Vezměte v úvahu následující Details People komponenty a :
- Komponenta
Detailspřijímá data ( ) z nadřazenéDataPeoplekomponenty, která se zobrazuje v<input>elementu . Každý daný zobrazený prvek může při výběru jednoho z prvků získat od uživatele<input>fokus<input>stránky. - Komponenta
Peoplevytvoří seznam objektů osob, které se mají zobrazit pomocíDetailskomponenty. Každé tři sekundy se do kolekce přidá nová osoba.
Tato ukázka umožňuje:
- Vyberte z
<input>několika vykreslenýchDetailskomponent. - Když se kolekce lidí automaticky zvětšuje, prostudujeme si chování fokusu stránky.
Shared/Details.razor:
<input value="@Data" />
@code {
[Parameter]
public string? Data { get; set; }
}
V následující komponentě má každá iterace přidání osoby za výsledek People OnTimerCallback opětovné sestavení celé Blazor kolekce. Stránka se zaměřuje na stejnou pozici indexu prvků, takže se fokus při každém přidání <input> osoby posune. Posun fokusu od toho, co uživatel vybral, není žádoucí chování. Po demonstraci špatného chování s následující komponentou se atribut direktivy používá @key ke zlepšení uživatelského prostředí.
Pages/People.razor:
@page "/people"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="@person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string? Data { get; set; }
}
}
Obsah kolekce se people změní pomocí vkládaných, odstraněných nebo přeřazených položek. Rerendering může vést k viditelným rozdílům v chování. Pokaždé, když je osoba vložena do kolekce, obdrží předchozí prvek aktuálně people zaměřeného prvku fokus. Fokus uživatele se ztratí.
Proces mapování prvků nebo součástí na kolekci lze řídit pomocí @key atributu direktivy. Použití zaručuje zachování prvků nebo komponent na základě @key hodnoty klíče. Pokud je Details komponenta v předchozím příkladu klíčová pro person položku, ignoruje komponenty Blazor rerenderingu, které Details se nezměnily.
Chcete-li upravit komponentu tak, aby se atribut direktivy s People @key people kolekcí, <Details> aktualizujte element na následující:
<Details @key="person" Data="@person.Data" />
Když se people kolekce změní, přidružení mezi instancemi a Details person instancemi se zachová. Při vložení na začátek kolekce se na odpovídající pozici vloží jedna Person Details nová instance. Ostatní instance zůstávají beze změny. Proto se fokus uživatele neztratí, když se do kolekce přidávají lidé.
Jiné aktualizace kolekcí vykazují při použití atributu @key direktiv stejné chování:
- Pokud je instance odstraněna z kolekce, z uživatelského rozhraní se odebere pouze odpovídající instance komponenty. Ostatní instance zůstávají beze změny.
- Pokud jsou položky kolekce znovu seřazené, odpovídající instance komponent se zachovají a znovu seřazené v uživatelském rozhraní.
Důležité
Klíče jsou místní pro každý prvek nebo komponentu kontejneru. Klíče se nerovná globálně v rámci dokumentu.
Kdy použít @key
Obvykle je vhodné použít vždy, když se vykreslí seznam (například v bloku) a existuje vhodná hodnota pro @key foreach definování @key .
Můžete také použít k zachování podstromu elementu nebo komponenty, pokud se objekt nezmění, jak @key je vidět v následujících příkladech.
Příklad 1:
<li @key="person">
<input value="@person.Data" />
</li>
Příklad 2:
<div @key="person">
@* other HTML elements *@
</div>
Pokud se person instance změní, @key direktiva atributu vynutí Blazor následující:
- Zahodí
<li>celé nebo a jejich<div>potomky. - Znovu sestavte podstrom v uživatelském rozhraní s novými prvky a komponentami.
To je užitečné k zaručení, že při změně kolekce v rámci podstromu se nezachová žádný stav uživatelského rozhraní.
Rozsah @key
Direktiva @key atributu je vymezena na své vlastní elementy na stejné úrovni v rámci nadřazeného objektu.
Představte si následující příklad. Klíče first second a jsou porovnány proti sobě navzájem v rámci stejného oboru vnějšího <div> prvku:
<div>
<div @key="first">...</div>
<div @key="second">...</div>
</div>
Následující příklad ukazuje a first klíče ve vlastních oborech, které spolu nesouvisejí a nemají second na sebe vliv. Každý @key obor se vztahuje pouze na nadřazený <div> prvek, nikoli napříč nadřazenými <div> elementy:
<div>
<div @key="first">...</div>
</div>
<div>
<div @key="second">...</div>
</div>
Pro Details komponentu zobrazenou výše následující příklady vykreslují data v rámci stejného oboru a person @key demonstrují typické případy použití pro @key :
<div>
@foreach (var person in people)
{
<Details @key="person" Data="@person.Data" />
}
</div>
@foreach (var person in people)
{
<div @key="person">
<Details Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li @key="person">
<Details Data="@person.Data" />
</li>
}
</ol>
V následujících příkladech je @key rozsah pouze na prvek nebo , který <div> <li> obklopuje každou Details instanci komponenty. Proto data pro každý člen kolekce nejsou klíčová pro každou person people instanci v rámci person vykreslených Details komponent. Při použití se vyhněte následujícím @key vzorům:
@foreach (var person in people)
{
<div>
<Details @key="person" Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li>
<Details @key="person" Data="@person.Data" />
</li>
}
</ol>
Kdy nepou3/4ít @key
Při vykreslování s je náklady na @key výkon. Náklady na výkon nejsou velké, ale určují, jestli je zachování @key elementu nebo komponenty přínosné pro aplikaci.
I v případě, že není použit, zachová co nejvíce podřízený prvek a @key Blazor instance komponent. Jedinou výhodou použití je kontrola nad mapováním instancí modelu na zachované instance komponent místo výběru @key Blazor mapování.
Hodnoty, které se používají pro @key
Obecně má smysl pro zadat jednu z následujících @key hodnot:
- Modelovat instance objektů. Například instance
Person(person) byla použita v předchozím příkladu. Tím se zajistí zachování na základě rovnosti odkazů na objekt. - Jedinečné identifikátory. Jedinečné identifikátory mohou být například založeny na hodnotách primárního klíče typu
intstring, neboGuid.
Ujistěte se, že hodnoty @key použité pro se nevychýlou. Pokud jsou v rámci stejného nadřazeného elementu zjištěny kolizované hodnoty, vyvolá výjimku, protože nemůže deterministicky mapovat staré prvky nebo komponenty na Blazor nové prvky nebo komponenty. Používejte pouze odlišné hodnoty, například instance objektů nebo hodnoty primárního klíče.
Použití atributu
Atributy lze použít na součásti s @attribute direktivou . Následující příklad použije [Authorize] atribut na třídu komponenty:
@page "/"
@attribute [Authorize]
Podmíněné atributy elementu HTML
Vlastnosti atributu elementu HTML jsou podmíněně nastaveny na základě hodnoty .NET. Pokud je hodnota false nebo , vlastnost není null nastavená. Pokud je hodnota true , nastaví se vlastnost .
V následujícím příkladu IsCompleted určuje, zda <input> je vlastnost checked elementu nastavena.
Pages/ConditionalAttribute.razor:
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
Další informace naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core.
Upozornění
Některé atributy HTML, například , fungují aria-pressed správně, pokud je typ .NET bool . V těchto případech použijte string místo typu bool typ .
Nezpracovaný kód HTML
Řetězce se obvykle vykreslují pomocí textových uzlů modelu DOM, což znamená, že všechny značky, které mohou obsahovat, jsou ignorovány a považovány za literálový text. Pokud chcete vykreslit nezpracovaný kód HTML, zabalte obsah HTML do MarkupString hodnoty. Hodnota se parsuje jako HTML nebo SVG a vloží se do modelu DOM.
Upozornění
Vykreslování nezpracovaných kódu HTML vytvořených z jakéhokoli nedůvěryhodného zdroje je bezpečnostním rizikem a měli byste se jim vždy vyhnout.
Následující příklad ukazuje použití typu k přidání bloku statického obsahu HTML do MarkupString vykreslené výstupu komponenty.
Pages/MarkupStringExample.razor:
@page "/markup-string-example"
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
Razor Šablony
Fragmenty vykreslování je možné definovat pomocí syntaxe šablony pro Razor definování fragmentu uživatelského rozhraní. Razor Šablony používají následující formát:
@<{HTML tag}>...</{HTML tag}>
Následující příklad ukazuje, jak zadat RenderFragment a RenderFragment<TValue> hodnoty a vykreslit šablony přímo v součásti. Fragmenty vykreslování mohou být také předány jako argumenty součástem šablon.
Pages/RazorTemplate.razor:
@page "/razor-template"
@timeTemplate
@petTemplate(new Pet { Name = "Nutty Rex" })
@code {
private RenderFragment timeTemplate = @<p>The time is @DateTime.Now.</p>;
private RenderFragment<Pet> petTemplate = (pet) => @<p>Pet: @pet.Name</p>;
private class Pet
{
public string? Name { get; set; }
}
}
Vykreslený výstup předchozího kódu:
<p>The time is 4/19/2021 8:54:46 AM.</p>
<p>Pet: Nutty Rex</p>
Statické prostředky
Blazorpostupuje podle konvence ASP.NET Core aplikací pro statické prostředky. Statické prostředky se nacházejí ve web root wwwroot složce nebo složkách projektu ve wwwroot složce.
Použijte základní cestu ( / ) pro odkaz na webový kořenový adresář pro statický prostředek. V následujícím příkladu logo.png je fyzicky umístěný ve {PROJECT ROOT}/wwwroot/images složce. {PROJECT ROOT} je kořenový adresář projektu aplikace.
<img alt="Company logo" src="/images/logo.png" />
Komponenty nepodporují vlnové lomítko ( ~/ ).
Informace o nastavení základní cesty aplikace najdete v tématu Hostování a nasazení ASP.NET Core Blazor .
V součástech nejsou podporovány pomocníky značek.
Tag Helpers nepodporuje se v součástech. Chcete-li poskytnout funkci, jako je například Pomocník pro Blazor vytváření značek, vytvořte komponentu se stejnou funkcí jako pomocník značek a místo ní použijte komponentu.
Obrázky ve formátu SVG (Scalable Vector Graphics)
Vzhledem k tomu, že Blazor VYKRESLUJE HTML, obrázky podporované prohlížečem, včetně obrázků SVG (Scalable Vector Graphics) ( .svg ), jsou podporovány prostřednictvím <img> značky:
<img alt="Example image" src="image.svg" />
Podobně jsou obrázky SVG podporovány v pravidlech CSS souboru šablony stylů ( .css ):
.element-class {
background-image: url("image.svg");
}
Blazor podporuje <foreignObject> element pro zobrazení libovolného HTML v rámci SVG. Označení může představovat libovolný HTML, a RenderFragment nebo Razor komponentu.
Následující příklad ukazuje:
- Zobrazení a
string(@message). - Obousměrná vazba s
<input>prvkem avaluepolem. RobotKomponenta.
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" rx="10" ry="10" width="200" height="200" stroke="black"
fill="none" />
<foreignObject x="20" y="20" width="160" height="160">
<p>@message</p>
</foreignObject>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject width="200" height="200">
<label>
Two-way binding:
<input @bind="value" @bind:event="oninput" />
</label>
</foreignObject>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject>
<Robot />
</foreignObject>
</svg>
@code {
private string message = "Lorem ipsum dolor sit amet, consectetur adipiscing " +
"elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
private string value;
}
Chování vykreslování prázdných znaků
Pokud se @preservewhitespace direktiva nepoužívá s hodnotou true , je ve výchozím nastavení odebrána nadbytečné prázdné znaky, pokud:
- Na začátku nebo na konci elementu.
- Na začátku nebo na konci v RenderFragment / RenderFragment<TValue> parametru (například podřízený obsah předaný do jiné součásti).
- Předchází nebo následuje blok kódu jazyka C#, například
@ifnebo@foreach.
Odebrání prázdného znaku může mít vliv na Vykreslený výstup při použití pravidla šablony stylů CSS, například white-space: pre . Chcete-li zakázat tuto optimalizaci výkonu a zachovat prázdné znaky, proveďte jednu z následujících akcí:
- Přidejte
@preservewhitespace truedirektivu do horní části Razor souboru (.razor), abyste použili předvolby pro konkrétní komponentu. - Přidejte
@preservewhitespace truedirektivu do_Imports.razorsouboru, chcete-li použít předvolby pro podadresář nebo na celý projekt.
Ve většině případů se nevyžaduje žádná akce, protože aplikace obvykle často fungují normálně (ale rychleji). Pokud odstranění prázdných znaků způsobí problém vykreslování konkrétní součásti, použijte @preservewhitespace true v této součásti k zakázání této optimalizace.
Podpora parametrů obecného typu
@typeparamDirektiva deklaruje parametr obecného typu pro generovanou třídu komponenty:
@typeparam TItem
Syntaxe jazyka C# s where omezením typu je podporována:
@typeparam TEntity where TEntity : IEntity
Další informace najdete v následujících článcích:
Vykreslení Razor komponent z JavaScriptu
Razor komponenty lze pro stávající aplikace JS dynamicky vykreslovat z JavaScriptu (JS).
Chcete-li vykreslit Razor komponentu z js, zaregistrujte komponentu jako kořenovou komponentu pro vykreslování js a přiřaďte komponentu identifikátoru:
V Blazor Server aplikaci upravte volání AddServerSideBlazor v
Program.cs:builder.Services.AddServerSideBlazor(options => { options.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter"); });Poznámka
Předchozí příklad kódu vyžaduje obor názvů pro součásti aplikace (například
using BlazorSample.Pages;) vProgram.cssouboru.V Blazor WebAssembly aplikaci zavolejte RegisterForJavaScript na RootComponents
Program.cs:builder.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");Poznámka
Předchozí příklad kódu vyžaduje obor názvů pro součásti aplikace (například
using BlazorSample.Pages;) vProgram.cssouboru.
Načtěte Blazor do aplikace js ( blazor.server.js nebo blazor.webassembly.js ). Vykreslete komponentu z JS do prvku kontejneru pomocí registrovaného identifikátoru a předáním parametrů komponenty podle potřeby:
let containerElement = document.getElementById('my-counter');
await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
Blazor vlastní elementy
experimentální podpora je k dispozici pro vytváření vlastních elementů pomocí Microsoft.AspNetCore.Components.CustomElements balíčku NuGet. Vlastní prvky používají rozhraní Standard HTML k implementaci vlastních prvků HTML.
Registrace kořenové komponenty jako vlastního elementu:
V Blazor Server aplikaci upravte volání AddServerSideBlazor v
Program.cs:builder.Services.AddServerSideBlazor(options => { options.RootComponents.RegisterAsCustomElement<Counter>("my-counter"); });Poznámka
Předchozí příklad kódu vyžaduje obor názvů pro součásti aplikace (například
using BlazorSample.Pages;) vProgram.cssouboru.V Blazor WebAssembly aplikaci zavolejte
RegisterAsCustomElementna RootComponentsProgram.cs:builder.RootComponents.RegisterAsCustomElement<Counter>("my-counter");Poznámka
Předchozí příklad kódu vyžaduje obor názvů pro součásti aplikace (například
using BlazorSample.Pages;) vProgram.cssouboru.
Použijte vlastní element s libovolným webovým rozhraním. například vlastní element čítače se používá v aplikaci React s následujícím kódem:
<my-counter increment-amount={incrementAmount}></my-counter>
Úplný příklad, jak vytvořit vlastní prvky pomocí Blazor , naleznete v Blazor projektu Sample Custom Elements.
Upozornění
Funkce Custom Elements je v současné době experimentální, nepodporované a může se kdykoli změnit nebo odebrat. Uvítáme vaše názory na to, jak dobře tento konkrétní přístup splňuje vaše požadavky.
generovat komponenty Angular a React
vygenerujte komponenty javascriptu (JS) specifické pro rozhraní z Razor komponent pro webová rozhraní, například Angular nebo React. Tato funkce není součástí rozhraní .NET 6, ale je povolena novou podporou pro vykreslování Razor komponent z js. ukázka generace komponent JS v GitHub ukazuje, jak generovat Angular a React komponenty z Razor komponent. další informace najdete v souboru ukázkové aplikace GitHub README.md .
Upozornění
funkce komponent Angular a React jsou aktuálně experimentální, nepodporované a můžou se kdykoli změnit nebo odebrat. Uvítáme vaše názory na to, jak dobře tento konkrétní přístup splňuje vaše požadavky.
Blazoraplikace jsou sestavené pomocí Razor komponent. Komponenta je samostatně obsažená část uživatelského rozhraní s logikou zpracování, která umožňuje dynamické chování. Komponenty mohou být vnořené, opakovaně používané, sdílené mezi projekty a používány v aplikacích MVC a Razor Pages.
Třídy komponent
Komponenty jsou implementovány pomocí kombinace kódu jazyka C# a HTML v Razor souborech součástí s .razor příponou souboru.
Razor syntaktick
Komponenty používají Razor syntaxi. Dvě Razor funkce jsou široce používány komponentami, direktivami a vlastnostmi direktiv. Jedná se o vyhrazená klíčová slova s předponou @ , která se zobrazí v Razor kódu:
- Direktivy: Změňte způsob, jakým jsou analyzovány značky komponenty nebo funkce. Například
@pagedirektiva určuje směrovatelný komponentu se šablonou směrování a je možné ji získat přímo pomocí žádosti uživatele v prohlížeči na konkrétní adrese URL. - Atributy direktiv: Změna způsobu, jakým je prvek komponenty analyzován nebo funkce. Například
@bindatribut direktiva pro<input>prvek váže data k hodnotě elementu.
Direktivy a direktivy používané v součástech jsou vysvětleny dále v tomto článku a v dalších článcích Blazor sady dokumentace. Obecné informace o Razor syntaxi naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core .
Názvy
Název součásti musí začínat velkým znakem:
ProductDetail.razorje platný.- Formát
productDetail.razorje neplatný.
BlazorMezi běžné konvence pojmenování používané v této Blazor dokumentaci patří:
- Cesty k souboru součástí používají velká † a malá písmena, než zobrazí příklady kódu komponenty. Cesty označují typické umístění složek. Například
Pages/ProductDetail.razoroznačuje, žeProductDetailkomponenta má název souboruProductDetail.razora je umístěn vePagessložce aplikace. - Cesty k souborům komponent pro směrovatelný komponenty odpovídají jejich adresám URL, které se zobrazují pro mezery mezi slovy v šabloně směrování komponenty. Například
ProductDetailsoučást s šablonou směrování/product-detail(@page "/product-detail") je požadována v prohlížeči na relativní adrese URL/product-detail.
†Případ typu Pascal (ve stylu CamelCase Case) je konvence pojmenování bez mezer a interpunkce a první písmeno každého slova, včetně prvního slova.
Směrování
Směrování do Blazor se dosahuje tím, že poskytuje šablonu směrování pro každou dostupnou součást aplikace s @page direktivou. Když Razor je zkompilován soubor s @page direktivou, vygenerovaná třída je dána RouteAttribute zadáním šablony trasy. V době běhu Směrovač vyhledává třídy komponent pomocí RouteAttribute a vykreslí, že každá komponenta má šablonu směrování, která odpovídá požadované adrese URL.
Následující HelloWorld komponenta používá šablonu směrování /hello-world . Vykreslená webová stránka pro komponentu je dosaženo na relativní adrese URL /hello-world . Při místním spuštění Blazor aplikace s výchozím protokolem, hostitelem a portem HelloWorld je tato součást vyžádána v prohlížeči na adrese https://localhost:5001/hello-world . Komponenty, které vytvářejí webové stránky, se obvykle nacházejí ve složce , ale k umístění součástí, včetně vnořených složek, můžete použít Pages libovolnou složku.
Pages/HelloWorld.razor:
@page "/hello-world"
<h1>Hello World!</h1>
Předchozí komponenta se načte v prohlížeči na bez ohledu na to, jestli komponentu přidáte do navigace v uživatelském /hello-world rozhraní aplikace. Volitelně můžete do komponenty přidat komponenty, aby se odkaz na komponentu objeví v navigaci aplikace založené NavMenu na uživatelském rozhraní.
Pro předchozí HelloWorld komponentu přidejte do NavLink součásti následující NavMenu komponentu. Přidejte komponentu do nové položky seznamu ( ) mezi značky NavLink <li>...</li> neuspořádaných seznamu ( <ul>...</ul> ).
Shared/NavMenu.razor:
<li class="nav-item px-3">
<NavLink class="nav-link" href="hello-world">
<span class="oi oi-list-rich" aria-hidden="true"></span> Hello World!
</NavLink>
</li>
Další informace, včetně popisů komponent NavLink a , najdete v tématu NavMenu ASP.NET Core Blazor úsek .
Kód
Uživatelské rozhraní komponenty je definováno pomocí Razor syntaxe, která se skládá z Razor kódu, jazyka C# a HTML. Při kompilaci aplikace se značky HTML a logika vykreslování v jazyce C# převedou do třídy komponent. Název vygenerované třídy odpovídá názvu souboru.
Členy třídy komponenty jsou definovány v jednom nebo více @code blocích. V @code blocích se stav komponenty specifikuje a zpracovává pomocí jazyka C#:
- Inicializátory vlastností a polí.
- Hodnoty parametrů z argumentů předané nadřazenými komponentami a parametry trasy.
- Metody pro zpracování událostí uživatele, události životního cyklu a logiku vlastních komponent
Členy komponent se používají v logice vykreslování pomocí výrazů jazyka C#, které začínají @ symbolem. Například pole jazyka C# se vykreslí předponou @ názvu pole. Následující Markup komponenta vyhodnotí a vykreslí:
headingFontStylejako hodnotu vlastnosti CSSfont-styleelementu heading.headingTextpro obsah elementu nadpisu.
Pages/Markup.razor:
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
Poznámka
Příklady v dokumentaci Blazor určují private modifikátor přístupu pro soukromé členy. Soukromé členy jsou vymezeny na třídu komponenty. Jazyk C# však předpokládá modifikátor přístupu, pokud není k dispozici žádný modifikátor přístupu, takže explicitní označení členů ve vašem vlastním kódu private private je volitelné. Další informace o modifikátorech přístupu najdete v tématu Modifikátory přístupu (Průvodceprogramováním v C#).
Tato rozhraní interně zpracovává komponentu jako strom vykreslování , což je kombinace modelu Blazor model DOM (Document Object Model) (DOM) a CSSOM (Cascading Style Sheet Object Model). Po počátečním vykreslení komponenty se vykreslovací strom komponenty znovu vygeneruje v reakci na události. Blazor porovná nový strom vykreslování s předchozím stromem vykreslování a použije všechny úpravy modelu DOM prohlížeče k zobrazení. Další informace naleznete v tématu BlazorASP.NET Core vykreslování komponent.
Komponenty jsou běžné třídy jazyka C# a lze je umístit kdekoli v rámci projektu. Komponenty, které vytvářejí webové stránky, se obvykle nacházejí ve Pages složce . Ne stránkované komponenty jsou často umístěny ve složce nebo ve vlastní Shared složce přidané do projektu.
Vnořené komponenty
Komponenty mohou zahrnovat další komponenty tím, že je deklarují pomocí syntaxe HTML. Kód pro použití komponenty vypadá jako značka HTML, kde název značky je typ komponenty.
Vezměte v Heading úvahu následující komponentu, kterou mohou ostatní komponenty použít k zobrazení nadpisu.
Shared/Heading.razor:
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
Následující kód v HeadingExample komponentě vykreslí předchozí Heading komponentu v umístění, kde se <Heading /> značka nachází.
Pages/HeadingExample.razor:
@page "/heading-example"
<Heading />
Pokud komponenta obsahuje prvek HTML s velkým prvním písmenem, které neodpovídá názvu komponenty ve stejném oboru názvů, vysílá se upozornění, že má prvek neočekávaný název. Přidáním direktivy pro obor názvů komponenty je @using komponenta dostupná, což upozornění vyřeší. Další informace najdete v části Obory názvů.
Příklad komponenty zobrazený v této části nemá direktivu , takže komponenta není přímo přístupná uživateli prostřednictvím přímého požadavku Heading @page v Heading prohlížeči. Jakákoli komponenta s @page direktivou však může být vnořena do jiné součásti. Pokud by byla komponenta přímo přístupná zahrnutím do horní části souboru, vykreslí se komponenta pro požadavky prohlížeče na Heading @page "/heading" adrese i Razor /heading /heading-example .
Obory názvů
Obor názvů komponenty se obvykle odvozuje z kořenového oboru názvů aplikace a umístění komponenty (složky) v aplikaci. Pokud je kořenový obor názvů aplikace a BlazorSample Counter komponenta se nachází ve Pages složce :
- Obor
Counternázvů komponenty jeBlazorSample.Pages. - Plně kvalifikovaný název typu komponenty je
BlazorSample.Pages.Counter.
Pro vlastní složky, které uchová součásti, přidejte direktivu do nadřazené komponenty nebo @using do souboru _Imports.razor aplikace. V následujícím příkladu jsou součásti Components ve složce dostupné:
@using BlazorSample.Components
Poznámka
@using Direktivy v _Imports.razor souboru jsou použity pouze pro soubory ( ), nikoli pro soubory Razor .razor jazyka C# ( .cs ).
Na komponenty je také možné odkazovat pomocí plně kvalifikovaných názvů, což nevyžaduje @using direktivu . Následující příklad přímo odkazuje ProductDetail na komponentu Components ve složce aplikace:
<BlazorSample.Components.ProductDetail />
Obor názvů komponenty, pomocí které je autorován, je založen na Razor následujících vlastnostech (v pořadí podle priority):
- Direktiva
@namespacev kódu Razor souboru (například@namespace BlazorSample.CustomNamespace). - Projekt je v
RootNamespacesouboru projektu (například<RootNamespace>BlazorSample</RootNamespace>). - Název projektu převzatý z názvu souboru projektu ( ) a cestu z kořenového adresáře projektu
.csprojke komponentě. Například rozhraní překládá{PROJECT ROOT}/Pages/Index.razors oborem názvů projektuBlazorSample( ) na obor názvů proBlazorSample.csprojBlazorSample.PagesIndexkomponentu.{PROJECT ROOT}je kořenová cesta projektu. Komponenty dodržují pravidla vazby názvů jazyka C#. Pro komponentu v tomto příkladu jsou součástí v oboruIndexvšechny komponenty:- Ve stejné složce:
Pages. - Komponenty v kořenovém adresáři projektu, které explicitně nezadá jiný obor názvů.
- Ve stejné složce:
Následující možnosti se nepodporují:
global::Kvalifikace.- Import komponent s příkazy s
usingaliasy Například@using Foo = Barse nepodporuje. - Částečně kvalifikované názvy. Například nelze přidat do komponenty a poté odkazovat na komponentu ve složce aplikace
@using BlazorSampleNavMenu( ) pomocíSharedShared/NavMenu.razor<Shared.NavMenu></Shared.NavMenu>.
Podpora částečné třídy
Komponenty jsou generovány jako částečné třídy jazyka C# a jsou vytvořeny pomocí jednoho z následujících přístupů:
- Jeden soubor obsahuje kód jazyka C# definovaný v jednom nebo více
@codeblocích, kód HTML a Razor kód. Blazor Šablony projektů definují své komponenty pomocí tohoto přístupu s jedním souborem. - Kód HTML Razor a kód se umístí do souboru ( Razor
.razor). Kód jazyka C# je umístěn do souboru na pozadí definovaného jako částečná třída (.cs).
Poznámka
Šablony stylů komponent, které definují styly specifické pro komponentu, je samostatný soubor ( .css ). Blazor Izolace šablon stylů CSS je popsána dále v ASP.NET Core Blazor Izolace šablon stylů CSS části .
Následující příklad ukazuje výchozí Counter komponentu s @code blokem v aplikaci vygenerované ze Blazor šablony projektu. Kód v jazyce C# a kód jsou ve stejném souboru. Toto je nejběžnější přístup při vytváření komponent.
Pages/Counter.razor:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Následující komponenta rozdělí kód HTML a kód z kódu C# pomocí souboru kódu na pozadí Counter Razor s částečnou třídou:
Pages/CounterPartialClass.razor:
@page "/counter-partial-class"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
Pages/CounterPartialClass.razor.cs:
namespace BlazorSample.Pages
{
public partial class CounterPartialClass
{
private int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
}
}
@using Direktivy v _Imports.razor souboru jsou použity pouze pro soubory ( ), nikoli pro soubory Razor .razor jazyka C# ( .cs ). Podle potřeby přidejte obory názvů do souboru částečné třídy.
Typické obory názvů používané komponentami:
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
Typické obory názvů zahrnují také obor názvů aplikace a obor názvů odpovídající složce Shared aplikace:
using BlazorSample;
using BlazorSample.Shared;
Určení základní třídy
Direktiva @inherits slouží k určení základní třídy pro komponentu. Následující příklad ukazuje, jak může komponenta dědit základní třídu k poskytnutí vlastností a metod komponenty. Základní BlazorRocksBase třída je odvozena z třídy ComponentBase .
Pages/BlazorRocks.razor:
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
BlazorRocksBase.cs:
using Microsoft.AspNetCore.Components;
namespace BlazorSample
{
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
}
Parametry komponenty
Parametry komponenty předá data komponentě a jsou definovány pomocí veřejných vlastností jazyka C# ve třídě komponenty s [Parameter] atributem. V následujícím příkladu se předá integrovaný typ odkazu ( ) a uživatelem definovaný typ odkazu System.String ( ) jako parametry PanelBody součásti.
PanelBody.cs:
public class PanelBody
{
public string Text { get; set; }
public string Style { get; set; }
}
Shared/ParameterChild.razor:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">@Title</div>
<div class="card-body" style="font-style:@Body.Style">
@Body.Text
</div>
</div>
@code {
[Parameter]
public string Title { get; set; } = "Set By Child";
[Parameter]
public PanelBody Body { get; set; } =
new()
{
Text = "Set by child.",
Style = "normal"
};
}
Upozornění
Zadání počátečních hodnot parametrů součásti je podporováno, ale nevytvářejte komponentu, která po prvním vykreslení komponenty zapisuje do vlastních parametrů. Další informace najdete v části Přepsané parametry tohoto článku.
Parametry Title Body komponenty a jsou nastaveny pomocí argumentů ve značce HTML, která ParameterChild vykresluje instanci komponenty. Následující ParameterParent komponenta vykreslí dvě ParameterChild komponenty:
- První
ParameterChildkomponenta se vykreslí bez poskytnutí argumentů parametrů. - Druhá komponenta přijímá hodnoty pro a z komponenty, která používá explicitní výraz
ParameterChildTitleBodyParameterParentjazyka C# k nastavení hodnotPanelBodyvlastností objektu .
Pages/ParameterParent.razor:
@page "/parameter-parent"
<h1>Child component (without attribute values)</h1>
<ParameterChild />
<h1>Child component (with attribute values)</h1>
<ParameterChild Title="Set by Parent"
Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />
Následující kód HTML vykreslený z komponenty zobrazuje výchozí hodnoty komponenty, pokud komponenta nezadá ParameterParent ParameterChild hodnoty parametrů ParameterParent komponenty. Když ParameterParent komponenta poskytuje hodnoty parametrů komponenty, nahradí ParameterChild výchozí hodnoty komponenty.
Poznámka
Pro přehlednost se vykreslované třídy stylu CSS nezobrazují v následujícím vykresleném kódu HTML.
<h1>Child component (without attribute values)</h1>
<div>
<div>Set By Child</div>
<div>Set by child.</div>
</div>
<h1>Child component (with attribute values)</h1>
<div>
<div>Set by Parent</div>
<div>Set by parent.</div>
</div>
Přiřaďte pole, vlastnost nebo výsledek metody v jazyce C# k parametru komponenty jako hodnotu atributu HTML pomocí Razor rezervovaného @ symbolu. Následující ParameterParent2 Komponenta zobrazí čtyři instance předchozí ParameterChild komponenty a nastaví jejich Title hodnoty parametrů na:
- Hodnota
titlepole - Výsledek
GetTitlemetody jazyka C#. - Aktuální místní datum v dlouhém formátu s ToLongDateString , které používá implicitní výraz jazyka C#.
panelDataTitleVlastnost objektu.
Pages/ParameterParent2.razor:
@page "/parameter-parent-2"
<ParameterChild Title="@title" />
<ParameterChild Title="@GetTitle()" />
<ParameterChild Title="@DateTime.Now.ToLongDateString()" />
<ParameterChild Title="@panelData.Title" />
@code {
private string title = "From Parent field";
private PanelData panelData = new();
private string GetTitle()
{
return "From Parent method";
}
private class PanelData
{
public string Title { get; set; } = "From Parent object";
}
}
Poznámka
Při přiřazování člena v jazyce C# k parametru komponenty, předponu člena se @ symbolem a nikdy neprefixujte atribut HTML parametru.
Správná odpověď.
<ParameterChild Title="@title" />
Nesprávná odpověď:
<ParameterChild @Title="title" />
Na rozdíl od na Razor stránkách ( .cshtml ) Blazor nemůže při vykreslování komponenty provádět asynchronní práci ve Razor výrazu. Důvodem je to Blazor , že je určený pro vykreslování interaktivních uživatelská rozhraní. V interaktivním uživatelském rozhraní musí obrazovka vždycky zobrazit něco, takže nemá smysl zablokovat tok vykreslování. Místo toho se provádí asynchronní práce během jedné z asynchronních událostí životního cyklu. Po každé asynchronní události životního cyklu se komponenta může znovu vykreslit. Následující Razor syntaxe není podporována :
<ParameterChild Title="@await ..." />
Kód v předchozím příkladu generuje při sestavení aplikace chybu kompilátoru :
Operátor await jde použít jenom v asynchronní metodě. Zvažte označení této metody pomocí modifikátoru Async a změnu jejího návratového typu na Task.
Chcete-li získat hodnotu Title parametru v předchozím příkladu asynchronně, komponenta může použít OnInitializedAsync událost životního cyklu, jak ukazuje následující příklad:
<ParameterChild Title="@title" />
@code {
private string title;
protected override async Task OnInitializedAsync()
{
title = await ...;
}
}
Další informace naleznete v tématu RazorASP.NET Core životní cyklus komponenty.
Použití explicitního Razor výrazu k zřetězení textu s výsledkem výrazu pro přiřazení k parametru není podporováno. Následující příklad hledá zřetězení textu " Set by " s hodnotou vlastnosti objektu. I když je tato syntaxe podporována na Razor stránce ( .cshtml ), není platná pro přiřazení k Title parametru dítěte v součásti. Následující Razor syntaxe není podporována :
<ParameterChild Title="Set by @(panelData.Title)" />
Kód v předchozím příkladu generuje při sestavení aplikace chybu kompilátoru :
Atributy komponenty nepodporují složitý obsah (smíšený jazyk C# a označení).
Pro podporu přiřazení složené hodnoty použijte metodu, pole nebo vlastnost. Následující příklad provádí zřetězení " Set by " a hodnotu vlastnosti objektu v metodě jazyka C# GetTitle :
Pages/ParameterParent3.razor:
@page "/parameter-parent-3"
<ParameterChild Title="@GetTitle()" />
@code {
private PanelData panelData = new();
private string GetTitle() => $"Set by {panelData.Title}";
private class PanelData
{
public string Title { get; set; } = "Parent";
}
}
Další informace naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core.
Upozornění
Poskytování počátečních hodnot pro parametry součásti je podporováno, ale nevytvářejte komponentu, která zapisuje do vlastních parametrů po prvním vygenerování součásti. Další informace najdete v části přepsané parametry tohoto článku.
Parametry součásti by měly být deklarovány jako Automatické vlastnosti, což znamená, že by neměly obsahovat vlastní logiku ve svých get nebo přístupových sestavách set . Například následující StartData vlastnost je automatická vlastnost:
[Parameter]
public DateTime StartData { get; set; }
Neumísťujte vlastní logiku do get set přístupového objektu nebo, protože parametry komponenty jsou čistě určené pro použití jako kanál pro nadřazenou komponentu pro tok informací pro podřízenou komponentu. Pokud set přístupový objekt vlastnosti podřízené komponenty obsahuje logiku, která způsobí převykreslování nadřazené komponenty, výsledky smyčky nekonečného vykreslování.
Transformace přijaté hodnoty parametru:
- Ponechte vlastnost parametru jako automatickou vlastnost, která bude reprezentovat dodaná nezpracovaná data.
- Vytvořte jinou vlastnost nebo metodu pro poskytnutí transformovaných dat na základě vlastnosti parametru.
Přepište OnParametersSetAsync pro transformaci přijatého parametru pokaždé, když se přijímají nová data.
Zápis počáteční hodnoty do parametru komponenty je podporován, protože přiřazení počátečních hodnot nekoliduje s Blazor automatickým vykreslováním komponent. Následující přiřazení aktuální místní proměnné DateTime with DateTime.Now StartData je platnou syntaxí v součásti:
[Parameter]
public DateTime StartData { get; set; } = DateTime.Now;
Po počátečním přiřazení DateTime.Now nepřiřazujte hodnotu StartData v kódu pro vývojáře. Další informace najdete v části přepsané parametry tohoto článku.
Parametry směrování
Komponenty mohou určovat parametry směrování v šabloně směrování @page direktivy. Blazor Směrovač používá parametry směrování k naplnění odpovídajících parametrů komponent.
Volitelné parametry směrování jsou podporovány. V následujícím příkladu text volitelné parametr přiřadí hodnotu segmentu směrování do Text Vlastnosti komponenty. Pokud segment není k dispozici, hodnota Text je nastavena na hodnotu " fantastic " v OnInitialized metodě životního cyklu.
Pages/RouteParameter.razor:
@page "/route-parameter/{text?}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
Informace o zachycování všech parametrů tras ( {*pageRoute} ), které zachycují cesty mezi více hranicemi složek, naleznete v tématu ASP.NET Core Blazor úsek .
Přepsatelné parametry
BlazorRozhraní obecně ukládá bezpečné přiřazení parametrů z nadřazené na podřízený:
- Parametry nejsou neočekávaně přepsány.
- Vedlejší účinky jsou minimalizovány. Například další vykreslování se vyhne, protože mohou vytvářet nekonečné smyčky vykreslování.
Podřízená komponenta přijímá nové hodnoty parametrů, které mohou přepsat existující hodnoty při novém vykreslení nadřazené komponenty. Náhodné přepsání hodnot parametrů v podřízené komponentě se často objevuje při vývoji komponenty s jedním nebo více parametry svázanými s daty a vývojář přímo do parametru v podřízeném objektu:
- Podřízená komponenta je vykreslena s jednou nebo více hodnotami parametrů z nadřazené komponenty.
- Podřízené zápisy přímo k hodnotě parametru.
- Nadřazená komponenta se znovu vykreslí a přepíše hodnotu parametru dítěte.
Možnost přepisování hodnot parametrů se rozšíří i na přistupující objekty vlastnosti podřízené součásti set .
Důležité
Naše obecné pokyny neumožňují vytvářet komponenty, které přímo zapisují do vlastních parametrů po prvním vygenerování součásti.
Vezměte v úvahu následující vadnou Expander součást:
- Vykreslí podřízený obsah.
- Přepíná zobrazení podřízeného obsahu s parametrem součásti (
Expanded). - Komponenta zapisuje přímo do
Expandedparametru, který demonstruje problém s přepsanými parametry a je třeba se jim vyhnout.
Poté, co následující Expander Komponenta demonstruje nesprávný přístup k tomuto scénáři, Expander je zobrazena upravená součást k předvedení správného přístupu. Následující příklady můžete umístit do místní ukázkové aplikace a vyzkoušet si popsané chování.
Shared/Expander.razor:
<div @onclick="Toggle" class="card bg-light mb-3" style="width:30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code>Expanded</code> = @Expanded)</h2>
@if (Expanded)
{
<p class="card-text">@ChildContent</p>
}
</div>
</div>
@code {
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
private void Toggle()
{
Expanded = !Expanded;
}
}
ExpanderKomponenta je přidána do následující ExpanderExample nadřazené komponenty, která může zavolat StateHasChanged :
- Volání StateHasChanged v kódu pro vývojáře upozorní komponentu, jejíž stav byl změněn, a obvykle aktivuje opakované vykreslení komponenty pro aktualizaci uživatelského rozhraní. StateHasChanged je podrobněji popsán dále v částech RazorASP.NET Core životní cyklus komponenty a BlazorASP.NET Core vykreslování komponent .
@onclickAtribut direktivy tlačítka připojí obslužnou rutinu události konclickudálosti tlačítka. Zpracování událostí je podrobněji popsáno dále v ASP.NET Core Blazor zpracování událostí .
Pages/ExpanderExample.razor:
@page "/expander-example"
<Expander Expanded="true">
Expander 1 content
</Expander>
<Expander Expanded="true" />
<button @onclick="StateHasChanged">
Call StateHasChanged
</button>
Zpočátku se Expander komponenty chovají nezávisle při Expanded přepínání jejich vlastností. Podřízené komponenty udržují své stavy podle očekávání. Když StateHasChanged je volána v nadřazeném prvku, Expanded parametr první podřízené komponenty se obnoví zpět na původní hodnotu ( true ). Hodnota druhé Expander součásti Expanded není resetována, protože ve druhé komponentě není vykreslen žádný podřízený obsah.
Chcete-li zachovat stav v předchozím scénáři, použijte soukromé pole v Expander součásti k údržbě jeho přepnutého stavu.
Následující revidovaná Expander součást:
- Akceptuje
Expandedhodnotu parametru komponenty z nadřazené položky. - Přiřadí hodnotu parametru komponenty k soukromému poli (
expanded) vOnInitializedudálosti. - Používá soukromé pole k údržbě stavu přepínacího tlačítka, který ukazuje, jak se vyhnout zápisu přímo do parametru.
Poznámka
Rada v této části rozšiřuje na podobnou logiku v přístupových parametrech komponent set , což může vést k podobným nežádoucím vedlejším účinkům.
Shared/Expander.razor:
<div @onclick="Toggle" class="card bg-light mb-3" style="width:30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code>expanded</code> = @expanded)</h2>
@if (expanded)
{
<p class="card-text">@ChildContent</p>
}
</div>
</div>
@code {
private bool expanded;
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
protected override void OnInitialized()
{
expanded = Expanded;
}
private void Toggle()
{
expanded = !expanded;
}
}
Další informace najdete v tématu o Blazor dvou způsobech vazby – chyba (dotnet/aspnetcore #24599).
Podřízený obsah
Komponenty mohou nastavit obsah jiné součásti. Součást přiřazení poskytuje obsah mezi počátečními a ukončovacími značkami podřízené komponenty.
V následujícím příkladu RenderFragmentChild má komponenta ChildContent vlastnost, která představuje segment uživatelského rozhraní pro vykreslení jako RenderFragment . Pozice ChildContent v Razor kódu komponenty je místo, kde se obsah vykresluje v konečném výstupu HTML.
Shared/RenderFragmentChild.razor:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Child content</div>
<div class="card-body">@ChildContent</div>
</div>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
}
Důležité
Vlastnost, která přijímá RenderFragment obsah, musí být pojmenována ChildContent podle konvence.
Následující RenderFragmentParent Komponenta poskytuje obsah pro vykreslování RenderFragmentChild umístěním obsahu uvnitř značek pro otevírání a zavírání podřízené komponenty.
Pages/RenderFragmentParent.razor:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
Vzhledem k způsobu, jakým Blazor vykresluje podřízený obsah, vykreslování komponent uvnitř for smyčky vyžaduje proměnnou místního indexu, pokud se v obsahu komponenty používá proměnná přírůstkového cyklu RenderFragmentChild . Do předchozí součásti lze přidat následující příklad RenderFragmentParent :
<h1>Three children with an index variable</h1>
@for (int c = 0; c < 3; c++)
{
var current = c;
<RenderFragmentChild>
Count: @current
</RenderFragmentChild>
}
Alternativně použijte foreach smyčku Enumerable.Range místo for smyčky. Do předchozí součásti lze přidat následující příklad RenderFragmentParent :
<h1>Second example of three children with an index variable</h1>
@foreach (var c in Enumerable.Range(0,3))
{
<RenderFragmentChild>
Count: @c
</RenderFragmentChild>
}
Informace o tom, jak RenderFragment lze použít jako šablonu pro uživatelské rozhraní komponenty, najdete v následujících článcích:
Seskupováním atributů a libovolné parametry
Komponenty mohou kromě deklarovaných parametrů komponenty zachytit a vykreslovat další atributy. Další atributy mohou být zachyceny ve slovníku a poté splatted na prvek, když je komponenta vykreslena pomocí @attributes Razor atributu direktiva. Tento scénář je vhodný pro definování komponenty, která vytváří prvek značky, který podporuje nejrůznější přizpůsobení. Například může být zdlouhavé definovat atributy samostatně pro objekt <input> , který podporuje mnoho parametrů.
V následující Splat součásti:
- První
<input>prvek (id="useIndividualParams") používá parametry jednotlivých komponent. - Druhý
<input>element (id="useAttributesDict") používá atribut seskupováním.
Pages/Splat.razor:
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
Vykreslené <input> prvky na webové stránce jsou identické:
<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
Chcete-li přijmout libovolné atributy, definujte parametr komponenty s CaptureUnmatchedValues vlastností nastavenou na true :
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> InputAttributes { get; set; }
}
CaptureUnmatchedValuesVlastnost on [Parameter] umožňuje, aby parametr odpovídal všem atributům, které se neshodují s žádným jiným parametrem. Komponenta může definovat pouze jeden parametr s CaptureUnmatchedValues . Typ vlastnosti používaný pomocí CaptureUnmatchedValues musí být přiřazovatelné z Dictionary<string, object> řetězcových klíčů. Použití IEnumerable<KeyValuePair<string, object>> nebo IReadOnlyDictionary<string, object> jsou také možnosti v tomto scénáři.
Pozice @attributes relativní vzhledem k poloze atributů elementu je důležitá. Když @attributes jsou splatted na elementu, atributy jsou zpracovávány zprava doleva (poslední až první). Vezměte v úvahu následující příklad nadřazené komponenty, která využívá podřízenou komponentu:
Shared/AttributeOrderChild1.razor:
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
Pages/AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
AttributeOrderChild1 extra Atribut komponenty je nastaven na hodnotu napravo od @attributes . AttributeOrderParent1Vykreslená komponenta <div> obsahuje extra="5" při předání prostřednictvím dodatečného atributu, protože atributy jsou zpracovávány zprava doleva (poslední až první):
<div extra="5" />
V následujícím příkladu extra je pořadí a @attributes obráceno v podřízené komponentě <div> :
Shared/AttributeOrderChild2.razor:
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
Pages/AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
<div>Webová stránka vykreslená v nadřazené komponentě obsahuje extra="10" při předání prostřednictvím dalšího atributu:
<div extra="10" />
Zachytit odkazy na komponenty
Odkazy na komponenty poskytují způsob, jak odkazovat na instanci komponenty pro vystavování příkazů. Zachytit odkaz na komponentu:
- Přidejte
@refatribut do podřízené součásti. - Definujte pole stejného typu jako podřízená komponenta.
Při vykreslení komponenty je pole vyplněno instancí součásti. Pak můžete vyvolat metody .NET v instanci.
Vezměte v úvahu následující ReferenceChild komponentu, která při volání zaznamená zprávu ChildMethod .
Shared/ReferenceChild.razor:
@using Microsoft.Extensions.Logging
@inject ILogger<ReferenceChild> logger
@code {
public void ChildMethod(int value)
{
logger.LogInformation("Received {Value} in ChildMethod", value);
}
}
Odkaz na komponentu je vyplněn až po vykreslení komponenty a jejího výstupu obsahuje ReferenceChild element. Dokud se komponenta nevykresluje, neexistuje žádný odkaz na.
Chcete-li pracovat s odkazy na součásti po dokončení vykreslování komponenty, použijte OnAfterRender OnAfterRenderAsync metody nebo.
Chcete-li použít referenční proměnnou s obslužnou rutinou události, použijte výraz lambda nebo přiřaďte delegáta obslužné rutiny události v OnAfterRender OnAfterRenderAsync metodách nebo. Tím se zajistí, že referenční proměnná je přiřazena před přiřazením obslužné rutiny události.
Následující přístup lambda používá předchozí ReferenceChild komponentu.
Pages/ReferenceParent1.razor:
@page "/reference-parent-1"
<button @onclick="@(() => childComponent.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
}
Následující přístup delegáta používá předchozí ReferenceChild komponentu.
Pages/ReferenceParent2.razor:
@page "/reference-parent-2"
<button @onclick="callChildMethod">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
private Action callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent.ChildMethod(5);
}
}
Použijte kolekci k odkazování na komponenty ve smyčce. V následujícím příkladu:
- Komponenty jsou přidány do List<T> .
- Je vytvořeno tlačítko pro každou komponentu, která spustí odpovídající komponentu
ChildMethodindex komponenty v List<T> .
Pages/ReferenceParent3.razor pomocí předchozí ReferenceChild komponenty:
@page "/reference-parent-3"
<ul>
@for (int i = 0; i < 5; i++)
{
var index = i;
var v = r.Next(1000);
<li>
<ReferenceChild @ref="childComponent" />
<button @onclick="@(() => callChildMethod(index, v))">
Component index @index: Call <code>ReferenceChild.ChildMethod(@v)</code>
</button>
</li>
}
</ul>
@code {
private Random r = new();
private List<ReferenceChild> components = new();
private Action<int, int> callChildMethod;
private ReferenceChild childComponent
{
set => components.Add(value);
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod(int index, int value)
{
components.ElementAt(index).ChildMethod(value);
}
}
Při zachytávání odkazů na součásti použijte podobnou syntaxi pro zachycení odkazů na prvky, zachycení odkazů na součásti není funkce interoperability JavaScriptu. Odkazy na součásti nejsou předány kódu jazyka JavaScript. Odkazy na komponenty se používají pouze v kódu .NET.
Důležité
Nepoužívejte odkazy na součásti pro použití stavu podřízených komponent. Místo toho použijte běžné deklarativní parametry komponenty k předání dat podřízeným součástem. Výsledkem použití parametrů komponenty jsou podřízené komponenty, které jsou automaticky revykreslovány ve správný čas. Další informace najdete v části parametry komponenty a v BlazorASP.NET Core datová vazba článku.
Kontext synchronizace
Blazor používá kontext synchronizace ( SynchronizationContext ) k vykonání jediného logického vlákna provádění. Metody životního cyklu komponenty a zpětná volání událostí, která vyvolala, Blazor jsou spouštěna v kontextu synchronizace.
Blazor Serverkontext synchronizace se pokouší emulovat prostředí s jedním vláknem tak, aby přesně odpovídal modelu webového sestavení v prohlížeči, který je jediným vláknem. V jakémkoli daném časovém okamžiku je práce prováděna v přesně jednom vlákně, což má za následek dojem jednoho logického vlákna. Žádné dvě operace se neprovádějí současně.
Vyhněte se voláním blokujícím vlákna
Obecně platí, že v součástech Nevolejte následující metody. Následující metody zablokují vlákno spouštění, takže aplikace brání v pokračování v práci, dokud se podklady Task nedokončí:
Poznámka
Blazor Příklady dokumentace, které používají metody blokující vlákna uvedené v této části, používají pouze metody pro demonstrační účely, nikoli doporučené pokyny pro kódování. Například několik ukázek kódu komponenty simuluje dlouhotrvající proces voláním Thread.Sleep .
Vyvolat metody komponenty externě na stav aktualizace
V případě, že komponenta musí být aktualizována na základě externí události, jako je například časovač nebo jiné oznámení, použijte InvokeAsync metodu, která odesílá kód pro spuštění Blazor v kontextu synchronizace. Zvažte například následující službu oznamovatele , která může oznámit všechny součásti naslouchání o aktualizovaném stavu. UpdateMetodu lze volat z libovolného místa v aplikaci.
TimerService.cs:
using System;
using System.Timers;
using Microsoft.Extensions.Logging;
public class TimerService : IDisposable
{
private int elapsedCount;
private readonly ILogger<TimerService> logger;
private readonly NotifierService notifier;
private Timer timer;
public TimerService(NotifierService notifier, ILogger<TimerService> logger)
{
this.notifier = notifier;
this.logger = logger;
}
public void Start()
{
if (timer is null)
{
timer = new();
timer.AutoReset = true;
timer.Interval = 10000;
timer.Elapsed += HandleTimer;
timer.Enabled = true;
logger.LogInformation("Started");
}
}
private async void HandleTimer(object source, ElapsedEventArgs e)
{
elapsedCount += 1;
await notifier.Update("elapsedCount", elapsedCount);
logger.LogInformation($"elapsedCount: {elapsedCount}");
}
public void Dispose()
{
timer?.Dispose();
}
}
NotifierService.cs:
using System;
using System.Threading.Tasks;
public class NotifierService
{
public async Task Update(string key, int value)
{
if (Notify != null)
{
await Notify.Invoke(key, value);
}
}
public event Func<string, int, Task> Notify;
}
Zaregistrujte služby:
V Blazor WebAssembly aplikaci zaregistrujte služby jako singleton v
Program.cs:builder.Services.AddSingleton<NotifierService>(); builder.Services.AddSingleton<TimerService>();V Blazor Server aplikaci zaregistrujte služby podle oboru v
Startup.ConfigureServices:services.AddScoped<NotifierService>(); services.AddScoped<TimerService>();
NotifierServiceK aktualizaci součásti použijte.
Pages/ReceiveNotifications.razor:
@page "/receive-notifications"
@implements IDisposable
@inject NotifierService Notifier
@inject TimerService Timer
<h1>Receive Notifications</h1>
<h2>Timer Service</h2>
<button @onclick="StartTimer">Start Timer</button>
<h2>Notifications</h2>
<p>
Status:
@if (lastNotification.key is not null)
{
<span>@lastNotification.key = @lastNotification.value</span>
}
else
{
<span>Awaiting first notification</span>
}
</p>
@code {
private (string key, int value) lastNotification;
protected override void OnInitialized()
{
Notifier.Notify += OnNotify;
}
public async Task OnNotify(string key, int value)
{
await InvokeAsync(() =>
{
lastNotification = (key, value);
StateHasChanged();
});
}
private void StartTimer()
{
Timer.Start();
}
public void Dispose()
{
Notifier.Notify -= OnNotify;
}
}
V předchozím příkladu:
NotifierServicevyvoláOnNotifymetodu komponenty mimo Blazor kontext synchronizace.InvokeAsyncslouží k přepnutí do správného kontextu a vykreslení vykreslování do fronty. Další informace naleznete v tématu BlazorASP.NET Core vykreslování komponent.- Komponenta implementuje IDisposable . U
OnNotifydelegáta jeDisposezrušena odběr metody, která je volána rozhraním, když je komponenta vyřazena. Další informace naleznete v tématu RazorASP.NET Core životní cyklus komponenty.
Slouží @key k řízení uchovávání prvků a komponent.
Při vykreslování seznamu prvků nebo komponent a prvků nebo komponent se následně Blazor musí rozhodnout, které z předchozích prvků nebo komponent mohou být zachovány a jakým způsobem by měly být namapovány objekty modelu. Obvykle je tento proces automatický a může být ignorován, ale existují případy, kdy můžete chtít řídit proces.
Vezměte v úvahu Details následující People komponenty a:
DetailsKomponenta přijímá data (Data) z nadřazenéPeoplekomponenty, která je zobrazena v<input>elementu. Kterýkoli zobrazený<input>element může obdržet fokus stránky od uživatele při výběru jednoho z<input>prvků.PeopleKomponenta vytvoří seznam objektů Person pro zobrazení pomocíDetailskomponenty. Každé tři sekundy se do kolekce přidá nová osoba.
Tato ukázka vám umožní:
- Vyberte
<input>mezi několika vykreslenýmiDetailskomponentami. - Prostudujte si chování fokusu stránky při automatickém zvětšování kolekce osob.
Shared/Details.razor:
<input value="@Data" />
@code {
[Parameter]
public string Data { get; set; }
}
V následující People součásti Každá iterace přidání osoby ve OnTimerCallback výsledku Blazor sestaví celou kolekci. Fokus stránky zůstává ve stejné pozici indexu <input> prvků, takže se fokus posune pokaždé, když je někdo přidaný. Přesunutí fokusu směrem od toho, co uživatel vybral, není žádoucí chování. Po demonstraci špatného chování s následující komponentou se @key pro zlepšení uživatelského prostředí používá atribut direktivy.
Pages/People.razor:
@page "/people"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="@person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string Data { get; set; }
}
}
Obsah people kolekce se mění s vloženými, odstraněnými nebo znovu seřazenými položkami. Reprodukce může vést k viditelným rozdílům v chování. Pokaždé, když se do kolekce vloží osoba people , předchozí prvek aktuálně zaměřeného prvku dostane fokus. Dojde ke ztrátě fokusu uživatele.
Proces mapování elementů nebo komponent na kolekci lze řídit pomocí @key atributu direktiva. Použití @key zaručuje zachování prvků nebo komponent na základě hodnoty klíče. Pokud Details je komponenta v předchozím příkladu označena na person položce, Blazor ignoruje znovu Details součásti, které se nezměnily.
Chcete-li upravit People komponentu pro použití @key atributu direktiva v people kolekci, aktualizujte <Details> element na následující:
<Details @key="person" Data="@person.Data" />
Při people změně kolekce Details je zachováno přidružení mezi instancemi a person instancemi. Když Person je vložena na začátek kolekce, Details je do příslušné pozice vložena jedna nová instance. Ostatní instance zůstanou beze změny. Proto se fokus uživatele neztratí, protože se do kolekce přidávají uživatelé.
Další aktualizace kolekcí vykazují stejné chování při @key použití atributu direktiva:
- Pokud je instance odstraněna z kolekce, bude z uživatelského rozhraní odebrána pouze odpovídající instance komponenty. Ostatní instance zůstanou beze změny.
- Pokud jsou položky kolekce znovu seřazené, odpovídající instance komponent se zachovají a znovu seřazené v uživatelském rozhraní.
Důležité
Klíče jsou místní pro každý prvek nebo komponentu kontejneru. Klíče se nerovná globálně v rámci dokumentu.
Kdy použít @key
Obvykle je vhodné použít vždy, když se vykreslí seznam (například v bloku) a existuje vhodná hodnota pro @key foreach definování @key .
Můžete také použít k zachování podstromu elementu nebo komponenty, pokud se objekt nezmění, jak @key je vidět v následujících příkladech.
Příklad 1:
<li @key="person">
<input value="@person.Data" />
</li>
Příklad 2:
<div @key="person">
@* other HTML elements *@
</div>
Pokud se person instance změní, @key direktiva atributu vynutí Blazor následující:
- Zahodí
<li>celé nebo a jejich<div>potomky. - Znovu sestavte podstrom v uživatelském rozhraní s novými prvky a komponentami.
To je užitečné k zaručení, že při změně kolekce v podstromu se nezachová žádný stav uživatelského rozhraní.
Rozsah @key
Direktiva @key atributu je vymezena na své vlastní elementy na stejné úrovni v rámci nadřazeného objektu.
Představte si následující příklad. Klíče first second a jsou vzájemně porovnány v rámci stejného oboru vnějšího <div> prvku:
<div>
<div @key="first">...</div>
<div @key="second">...</div>
</div>
Následující příklad ukazuje a first klíče ve vlastních oborech, které spolu nesouvisejí a nemají second na sebe vliv. Každý @key obor se vztahuje pouze na nadřazený <div> prvek, nikoli napříč nadřazenými <div> elementy:
<div>
<div @key="first">...</div>
</div>
<div>
<div @key="second">...</div>
</div>
Pro Details komponentu zobrazenou výše následující příklady vykreslují data v rámci stejného oboru a person @key demonstrují typické případy použití pro @key :
<div>
@foreach (var person in people)
{
<Details @key="person" Data="@person.Data" />
}
</div>
@foreach (var person in people)
{
<div @key="person">
<Details Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li @key="person">
<Details Data="@person.Data" />
</li>
}
</ol>
V následujících příkladech je @key rozsah pouze na prvek nebo , který <div> <li> obklopuje každou Details instanci komponenty. Proto data pro každý člen kolekce nejsou klíčová pro každou person people instanci v rámci person vykreslených Details komponent. Při použití se vyhněte následujícím @key vzorům:
@foreach (var person in people)
{
<div>
<Details @key="person" Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li>
<Details @key="person" Data="@person.Data" />
</li>
}
</ol>
Kdy nepou3/4ít @key
Při vykreslování s je náklady na @key výkon. Náklady na výkon nejsou velké, ale určují, jestli je zachování @key elementu nebo komponenty přínosné pro aplikaci.
I v případě, že není použit, zachová co nejvíce podřízený prvek a @key Blazor instance komponent. Jedinou výhodou použití je kontrola nad mapováním instancí modelu na zachované instance komponent místo výběru @key Blazor mapování.
Hodnoty, které se používají pro @key
Obecně má smysl zadat jednu z následujících hodnot pro @key :
- Modelovat instance objektů. Například instance
Person(person) byla použita v předchozím příkladu. Tím se zajistí zachování na základě rovnosti odkazů na objekt. - Jedinečné identifikátory. Jedinečné identifikátory mohou být například založeny na hodnotách primárního klíče typu
intstring, neboGuid.
Ujistěte se, že hodnoty @key použité pro se nevychýlou. Pokud jsou v rámci stejného nadřazeného elementu zjištěny kolizované hodnoty, vyvolá výjimku, protože nemůže deterministicky mapovat staré prvky nebo komponenty na Blazor nové prvky nebo komponenty. Používejte pouze odlišné hodnoty, například instance objektů nebo hodnoty primárního klíče.
Použití atributu
Atributy lze použít na součásti s @attribute direktivou . Následující příklad aplikuje [Authorize] atribut na třídu komponenty:
@page "/"
@attribute [Authorize]
Podmíněné atributy elementu HTML
Vlastnosti atributu elementu HTML jsou podmíněně nastavené na základě hodnoty .NET. Pokud je hodnota false nebo , vlastnost není null nastavená. Pokud je hodnota true , nastaví se vlastnost .
V následujícím příkladu IsCompleted určuje, zda <input> je vlastnost checked elementu nastavena.
Pages/ConditionalAttribute.razor:
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
Další informace naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core.
Upozornění
Některé atributy HTML, například , fungují aria-pressed správně, pokud je typ .NET bool . V těchto případech použijte string místo typu bool typ .
Nezpracovaný kód HTML
Řetězce se obvykle vykreslují pomocí textových uzlů modelu DOM, což znamená, že všechny značky, které mohou obsahovat, jsou ignorovány a považovány za literálový text. Pokud chcete vykreslit nezpracovaný kód HTML, zabalte obsah HTML do MarkupString hodnoty. Hodnota se parsuje jako HTML nebo SVG a vloží se do modelu DOM.
Upozornění
Vykreslování nezpracovaných kódu HTML vytvořených z jakéhokoli nedůvěryhodného zdroje je bezpečnostním rizikem, a proto byste se měli vždy vyhnout.
Následující příklad ukazuje použití typu k přidání bloku statického obsahu HTML do MarkupString vykreslené výstupu komponenty.
Pages/MarkupStringExample.razor:
@page "/markup-string-example"
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
Razor Šablony
Fragmenty vykreslování je možné definovat pomocí syntaxe šablony pro Razor definování fragmentu uživatelského rozhraní. Razor Šablony používají následující formát:
@<{HTML tag}>...</{HTML tag}>
Následující příklad ukazuje, jak zadat RenderFragment RenderFragment<TValue> hodnoty a a vykreslit šablony přímo v komponentě. Fragmenty vykreslování lze také předat jako argumenty komponentám šablony.
Pages/RazorTemplate.razor:
@page "/razor-template"
@timeTemplate
@petTemplate(new Pet { Name = "Nutty Rex" })
@code {
private RenderFragment timeTemplate = @<p>The time is @DateTime.Now.</p>;
private RenderFragment<Pet> petTemplate = (pet) => @<p>Pet: @pet.Name</p>;
private class Pet
{
public string Name { get; set; }
}
}
Vykreslený výstup předchozího kódu:
<p>The time is 4/19/2021 8:54:46 AM.</p>
<p>Pet: Nutty Rex</p>
Statické prostředky
Blazorse řídí konvencí ASP.NET Core statické prostředky. Statické prostředky se nacházejí ve složce nebo složkách projektu web root ( wwwroot ) ve wwwroot složce.
Pokud chcete odkazovat na kořenový adresář webu statického assetu, použijte cestu relativní k základu ( / ). V následujícím příkladu logo.png je fyzicky umístěn ve {PROJECT ROOT}/wwwroot/images složce . {PROJECT ROOT} je kořen projektu aplikace.
<img alt="Company logo" src="/images/logo.png" />
Komponenty nepodporují notaci tildy a lomítka ( ~/ ).
Informace o nastavení základní cesty aplikace najdete v tématu Hostování a nasazení ASP.NET Core Blazor .
Komponenty nepodporují pomocné prvky značek.
Tag Helpers nejsou podporované v komponentách. Pokud chcete v nástroji poskytovat funkce jako pomocná funkce značek, vytvořte komponentu se stejnými funkcemi jako pomocná služba značek a místo ní Blazor použijte komponentu .
Obrázky SVG (Scalable Vector Graphics)
Vzhledem k tomu, že se vykresluje HTML, podporují se obrázky podporované prohlížečem, včetně obrázků Blazor SVG (Scalable Vector Graphics) ( .svg ), prostřednictvím <img> značky :
<img alt="Example image" src="image.svg" />
Podobně se obrázky SVG podporují v pravidlech CSS souboru šablony stylů .css ():
.element-class {
background-image: url("image.svg");
}
Chování vykreslování prázdných znaky
Pokud není direktiva použita s hodnotou , jsou ve výchozím nastavení odebrány další prázdné @preservewhitespace true znaky, pokud:
- Počáteční nebo koncové v rámci elementu.
- Počáteční nebo koncový obsah v RenderFragment / RenderFragment<TValue> rámci parametru (například podřízený obsah předaný jiné komponentě).
- Předchází nebo následuje blok kódu jazyka C#, například
@ifnebo@foreach.
Odebrání prázdných znaky může mít vliv na vykreslený výstup při použití pravidla CSS, například white-space: pre . Pokud chcete tuto optimalizaci výkonu zakázat a zachovat prázdné znaky, udělejte jednu z následujících akcí:
- Na začátek
@preservewhitespace truesouboru přidejte direktivu ( ), která Razor použije.razorpředvolbu pro konkrétní komponentu. - Přidejte
@preservewhitespace truedirektivu do_Imports.razorsouboru, aby se předvolba aplikuje na podadresář nebo na celý projekt.
Ve většině případů se nevyžaduje žádná akce, protože aplikace se obvykle chovají normálně (ale rychleji). Pokud prokládané prázdné znaky způsobí problém s vykreslováním pro konkrétní komponentu, pomocí v této @preservewhitespace true komponentě tuto optimalizaci zakažte.
Podpora parametrů obecného typu
Direktiva @typeparam deklaruje parametr obecného typu pro vygenerované třídy komponent:
@typeparam TItem
Další informace najdete v následujících článcích:
BlazorAplikace se sestaví pomocí Razor komponent. Komponenta je samostatná část uživatelského rozhraní s logikou zpracování umožňující dynamické chování. Komponenty je možné vnořovat, opakovaně používat, sdílet mezi projekty a používat v aplikacích MVC Razor a Pages.
Třídy komponent
Komponenty jsou implementovány pomocí kombinace kódu C# a HTML v Razor souborech součástí s .razor příponou souboru.
Razor Syntaxe
Komponenty používají Razor syntaxi. Komponenty, direktivy a atributy direktiv ve velké části Razor používají dvě funkce. Jedná se o vyhrazená klíčová slova s @ předponou , která se zobrazují v Razor kódu:
- Direktivy:Změna způsobu analýzy značek komponent nebo funkcí. Direktiva například určuje směrovatelnou komponentu se šablonou trasy a je k dispozici přímo požadavkem uživatele v prohlížeči na
@pagekonkrétní adrese URL. - Atributydirektivy: Změna způsobu analýzy elementu komponenty nebo funkcí. Například
@bindatribut direktiva pro<input>prvek váže data k hodnotě elementu.
Direktivy a direktivy používané v součástech jsou vysvětleny dále v tomto článku a v dalších článcích Blazor sady dokumentace. Obecné informace o Razor syntaxi naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core .
Názvy
Název součásti musí začínat velkým znakem:
ProductDetail.razorje platný.- Formát
productDetail.razorje neplatný.
BlazorMezi běžné konvence pojmenování používané v této Blazor dokumentaci patří:
- Cesty k souboru součástí používají velká † a malá písmena, než zobrazí příklady kódu komponenty. Cesty označují typické umístění složek. Například
Pages/ProductDetail.razoroznačuje, žeProductDetailkomponenta má název souboruProductDetail.razora je umístěn vePagessložce aplikace. - Cesty k souborům komponent pro směrovatelný komponenty odpovídají jejich adresám URL, které se zobrazují pro mezery mezi slovy v šabloně směrování komponenty. Například
ProductDetailsoučást s šablonou směrování/product-detail(@page "/product-detail") je požadována v prohlížeči na relativní adrese URL/product-detail.
†Případ typu Pascal (ve stylu CamelCase Case) je konvence pojmenování bez mezer a interpunkce a první písmeno každého slova, včetně prvního slova.
Směrování
Směrování do Blazor se dosahuje tím, že poskytuje šablonu směrování pro každou dostupnou součást aplikace s @page direktivou. Když Razor je zkompilován soubor s @page direktivou, vygenerovaná třída je dána RouteAttribute zadáním šablony trasy. V době běhu Směrovač vyhledává třídy komponent pomocí RouteAttribute a vykreslí, že každá komponenta má šablonu směrování, která odpovídá požadované adrese URL.
Následující HelloWorld komponenta používá šablonu směrování /hello-world . Vykreslená webová stránka pro komponentu je dosaženo na relativní adrese URL /hello-world . Při místním spuštění Blazor aplikace s výchozím protokolem, hostitelem a portem HelloWorld je tato součást vyžádána v prohlížeči na adrese https://localhost:5001/hello-world . Komponenty, které tvoří webové stránky, se obvykle nacházejí ve Pages složce, ale můžete použít libovolnou složku k ukládání součástí, včetně vnořených složek.
Pages/HelloWorld.razor:
@page "/hello-world"
<h1>Hello World!</h1>
Předchozí komponenta se načte v prohlížeči /hello-world bez ohledu na to, jestli tuto součást přidáte do navigace uživatelského rozhraní aplikace. Volitelně lze součásti přidat do NavMenu komponenty, takže se odkaz na komponentu zobrazí v navigaci na základě uživatelského rozhraní aplikace.
Pro předchozí HelloWorld komponentu přidejte NavLink do komponenty následující komponentu NavMenu . Přidejte NavLink komponentu do nové položky seznamu ( <li>...</li> ) mezi značkami neuspořádaného seznamu ( <ul>...</ul> ).
Shared/NavMenu.razor:
<li class="nav-item px-3">
<NavLink class="nav-link" href="hello-world">
<span class="oi oi-list-rich" aria-hidden="true"></span> Hello World!
</NavLink>
</li>
Další informace, včetně popisů NavLink NavMenu komponent a, naleznete v tématu ASP.NET Core Blazor úsek .
Kód
Uživatelské rozhraní komponenty je definováno pomocí Razor syntaxe, která se skládá z Razor značek, C# a HTML. Při kompilaci aplikace jsou značky HTML a vykreslování jazyka C# převedeny na třídu komponenty. Název generované třídy se shoduje s názvem souboru.
Členy třídy komponenty jsou definovány v jednom nebo více @code blocích. V @code blocích je stav součásti určen a zpracován v jazyce C#:
- Inicializátory vlastností a polí.
- Hodnoty parametrů z argumentů předaných nadřazenými komponentami a parametry směrování.
- Metody zpracování událostí uživatele, událostí životního cyklu a vlastní logiky komponent.
Členy součástí jsou používány v logice vykreslování pomocí výrazů jazyka C#, které začínají @ symbolem. Například pole C# se vykreslí pomocí předpony @ na název pole. Následující Markup Komponenta vyhodnocuje a vykresluje:
headingFontStylepro hodnotu vlastnosti CSSfont-styleprvku záhlaví.headingTextpro obsah elementu nadpisu.
Pages/Markup.razor:
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
Poznámka
Příklady v celé Blazor dokumentaci určují private modifikátor přístupu pro soukromé členy. Soukromé členy jsou vymezeny na třídu součásti. Jazyk C# však předpokládá private modifikátor přístupu, pokud není k dispozici žádný modifikátor přístupu, takže explicitní označení členů " private " ve vašem vlastním kódu je volitelné. Další informace o modifikátorech přístupu najdete v tématu modifikátory přístupu (Průvodce programováním v C#).
BlazorRozhraní zpracuje komponentu interně jako strom vykreslování, což je kombinace model DOM (Document Object Model) komponenty (DOM) a modelu objektu kaskádových stylů (CSSOM). Po prvním vykreslení komponenty se strom vykreslování komponenty znovu vygeneruje v reakci na události. Blazor Porovná nový strom vykreslování proti předchozímu stromu vykreslování a aplikuje všechny změny v modelu DOM prohlížeče pro zobrazení. Další informace naleznete v tématu BlazorASP.NET Core vykreslování komponent.
Komponenty jsou běžné třídy jazyka C# a lze je umístit kamkoli v rámci projektu. Komponenty, které tvoří webové stránky, se obvykle nacházejí ve Pages složce. Komponenty mimo stránku jsou často umístěny do Shared složky nebo vlastní složky přidané do projektu.
Vnořené součásti
Komponenty mohou zahrnovat další komponenty, které jsou deklarovány pomocí syntaxe jazyka HTML. Označení pro použití komponenty vypadá jako značka HTML, kde název značky je typ komponenty.
Vezměte v úvahu následující Heading komponentu, kterou mohou použít jiné komponenty k zobrazení záhlaví.
Shared/Heading.razor:
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
Následující značka v HeadingExample komponentě vykreslí předchozí Heading komponentu v umístění, kde <Heading /> se zobrazí značka.
Pages/HeadingExample.razor:
@page "/heading-example"
<Heading />
Pokud komponenta obsahuje element HTML s velkým prvním písmenem, které neodpovídá názvu komponenty v rámci stejného oboru názvů, je vygenerováno upozornění označující, že element má neočekávaný název. Přidání @using direktivy pro obor názvů součásti zpřístupňuje komponentu, která vyřeší upozornění. Další informace najdete v části obory názvů .
HeadingPříklad komponenty zobrazený v této části neobsahuje @page direktivu, takže Heading součást není přímo přístupná uživateli přes přímý požadavek v prohlížeči. Nicméně jakákoli součást s @page direktivou může být vnořena do jiné komponenty. Pokud Heading byla komponenta přímo přístupná, a to zahrnutím do @page "/heading" horní části Razor souboru, pak se komponenta vykreslí pro požadavky prohlížeče v obou /heading i /heading-example .
Obory názvů
Obor názvů komponenty obvykle je odvozen z kořenového oboru názvů aplikace a umístění komponenty (složka) v rámci aplikace. Pokud je kořenový obor názvů aplikace BlazorSample a součást se nachází Counter ve Pages složce:
CounterObor názvů součásti jeBlazorSample.Pages.- Plně kvalifikovaný název typu komponenty je
BlazorSample.Pages.Counter.
Pro vlastní složky, které obsahují součásti, přidejte @using do nadřazené komponenty nebo do souboru aplikace direktivu _Imports.razor . V následujícím příkladu jsou komponenty ve Components složce k dispozici:
@using BlazorSample.Components
Poznámka
@using direktivy v _Imports.razor souboru jsou aplikovány pouze na Razor soubory ( .razor ), nikoli soubory jazyka C# ( .cs ).
Na součásti lze také odkazovat pomocí jejich plně kvalifikovaných názvů, které nevyžadují @using direktivu. Následující příklad přímo odkazuje na ProductDetail komponentu ve Components složce aplikace:
<BlazorSample.Components.ProductDetail />
Obor názvů komponenty, která se vytvořila, Razor je založený na následujícím typu (v pořadí podle priority):
@namespaceDirektiva v Razor kódu souboru (například@namespace BlazorSample.CustomNamespace).- Projekt
RootNamespacev souboru projektu (například<RootNamespace>BlazorSample</RootNamespace>). - Název projektu, pořízený z názvu souboru projektu (
.csproj) a cesta z kořenového adresáře projektu k součásti. Například rozhraní se přeloží{PROJECT ROOT}/Pages/Index.razorpomocí oboru názvů projektuBlazorSample(BlazorSample.csproj) na obor názvůBlazorSample.PagesproIndexkomponentu.{PROJECT ROOT}je kořenová cesta projektu. Komponenty následují pravidla vazeb názvů C#. ProIndexkomponentu v tomto příkladu komponenty v oboru jsou všechny komponenty:- Ve stejné složce,
Pages. - Komponenty v kořenu projektu, které explicitně neurčují jiný obor názvů.
- Ve stejné složce,
Následující nejsou podporovány:
global::Kvalifikace.- Import komponent s příkazy s aliasem
using. Například@using Foo = Barnení podporován. - Částečně kvalifikované názvy. Například nemůžete přidat
@using BlazorSampledo komponenty a pak odkazovat naNavMenukomponentu veSharedsložce aplikace (Shared/NavMenu.razor) s<Shared.NavMenu></Shared.NavMenu>.
Podpora částečné třídy
Komponenty jsou generovány jako částečné třídy jazyka C# a jsou vytvořeny pomocí některého z následujících přístupů:
- Jeden soubor obsahuje kód C# definovaný v jednom nebo více
@codeblocích, značka HTML a Razor značky. Blazor šablony projektů definují své komponenty pomocí tohoto přístupu s jedním souborem. - HTML a Razor značky jsou umístěny v Razor souboru (
.razor). Kód jazyka C# je umístěn v souboru kódu na pozadí, který je definován jako částečná třída (.cs).
Následující příklad ukazuje výchozí Counter komponentu s @code blokem v aplikaci vygenerovanou Blazor šablonou projektu. Značky a kód jazyka C# jsou ve stejném souboru. Toto je nejběžnější přístup při vytváření součástí.
Pages/Counter.razor:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Následující Counter Komponenta rozdělí kód HTML a Razor značku z kódu jazyka C# pomocí souboru kódu na pozadí s částečnou třídou:
Pages/CounterPartialClass.razor:
@page "/counter-partial-class"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
Pages/CounterPartialClass.razor.cs:
namespace BlazorSample.Pages
{
public partial class CounterPartialClass
{
private int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
}
}
@using direktivy v _Imports.razor souboru jsou aplikovány pouze na Razor soubory ( .razor ), nikoli soubory jazyka C# ( .cs ). Podle potřeby přidejte do souboru dílčí třídy obory názvů.
Typické obory názvů používané součástmi:
using System.Net.Http;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
Typické obory názvů také zahrnují obor názvů aplikace a obor názvů odpovídající Shared složce aplikace:
using BlazorSample;
using BlazorSample.Shared;
Zadat základní třídu
@inheritsDirektiva slouží k určení základní třídy pro komponentu. Následující příklad ukazuje, jak může komponenta zdědit základní třídu pro poskytnutí vlastností a metod komponenty. BlazorRocksBaseZákladní třída je odvozena z ComponentBase .
Pages/BlazorRocks.razor:
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
BlazorRocksBase.cs:
using Microsoft.AspNetCore.Components;
namespace BlazorSample
{
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
}
Parametry součásti
Parametry komponenty přecházejí data na součásti a jsou definovány pomocí vlastností Public jazyka C# třídy Component s [Parameter] atributem. V následujícím příkladu je vestavěný odkazový typ ( System.String ) a uživatelsky definovaný typ odkazu ( PanelBody ) předány jako parametry součásti.
PanelBody.cs:
public class PanelBody
{
public string Text { get; set; }
public string Style { get; set; }
}
Shared/ParameterChild.razor:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">@Title</div>
<div class="card-body" style="font-style:@Body.Style">
@Body.Text
</div>
</div>
@code {
[Parameter]
public string Title { get; set; } = "Set By Child";
[Parameter]
public PanelBody Body { get; set; } =
new PanelBody()
{
Text = "Set by child.",
Style = "normal"
};
}
Upozornění
Poskytování počátečních hodnot pro parametry součásti je podporováno, ale nevytvářejte komponentu, která zapisuje do vlastních parametrů po prvním vygenerování součásti. Další informace najdete v části přepsané parametry tohoto článku.
Title Body Parametry komponenty a ParameterChild komponenty jsou nastaveny podle ARGUMENTŮ ve značce HTML, která vykresluje instanci komponenty. Následující ParameterParent Komponenta vykreslí dvě ParameterChild komponenty:
- První
ParameterChildKomponenta je vykreslena bez nutnosti zadávat argumenty parametru. - Druhá
ParameterChildKomponenta přijímá hodnoty proTitleaBodyzeParameterParentsoučásti, která používá explicitní výraz jazyka C# k nastavení hodnotPanelBodyvlastností.
Pages/ParameterParent.razor:
@page "/parameter-parent"
<h1>Child component (without attribute values)</h1>
<ParameterChild />
<h1>Child component (with attribute values)</h1>
<ParameterChild Title="Set by Parent"
Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />
Následující vykreslený kód HTML ze ParameterParent součásti zobrazuje ParameterChild výchozí hodnoty komponent, pokud ParameterParent Komponenta neposkytuje hodnoty parametrů komponenty. Pokud ParameterParent Komponenta poskytuje hodnoty parametrů komponenty, nahradí ParameterChild výchozí hodnoty součásti.
Poznámka
Pro přehlednost nejsou vykreslené třídy stylu CSS zobrazeny v následujícím vykresleném kódu HTML.
<h1>Child component (without attribute values)</h1>
<div>
<div>Set By Child</div>
<div>Set by child.</div>
</div>
<h1>Child component (with attribute values)</h1>
<div>
<div>Set by Parent</div>
<div>Set by parent.</div>
</div>
Přiřaďte pole, vlastnost nebo výsledek metody v jazyce C# k parametru komponenty jako hodnotu atributu HTML pomocí Razor rezervovaného @ symbolu. Následující ParameterParent2 Komponenta zobrazí čtyři instance předchozí ParameterChild komponenty a nastaví jejich Title hodnoty parametrů na:
- Hodnota
titlepole - Výsledek
GetTitlemetody jazyka C#. - Aktuální místní datum v dlouhém formátu s ToLongDateString , které používá implicitní výraz jazyka C#.
panelDataTitleVlastnost objektu.
Pages/ParameterParent2.razor:
@page "/parameter-parent-2"
<ParameterChild Title="@title" />
<ParameterChild Title="@GetTitle()" />
<ParameterChild Title="@DateTime.Now.ToLongDateString()" />
<ParameterChild Title="@panelData.Title" />
@code {
private string title = "From Parent field";
private PanelData panelData = new PanelData();
private string GetTitle()
{
return "From Parent method";
}
private class PanelData
{
public string Title { get; set; } = "From Parent object";
}
}
Poznámka
Při přiřazování člena v jazyce C# k parametru komponenty, předponu člena se @ symbolem a nikdy neprefixujte atribut HTML parametru.
Správná odpověď.
<ParameterChild Title="@title" />
Nesprávná odpověď:
<ParameterChild @Title="title" />
Na rozdíl od na Razor stránkách ( .cshtml ) Blazor nemůže při vykreslování komponenty provádět asynchronní práci ve Razor výrazu. Důvodem je to Blazor , že je určený pro vykreslování interaktivních uživatelská rozhraní. V interaktivním uživatelském rozhraní musí obrazovka vždycky zobrazit něco, takže nemá smysl zablokovat tok vykreslování. Místo toho se provádí asynchronní práce během jedné z asynchronních událostí životního cyklu. Po každé asynchronní události životního cyklu se komponenta může znovu vykreslit. Následující Razor syntaxe není podporována :
<ParameterChild Title="@await ..." />
Kód v předchozím příkladu generuje při sestavení aplikace chybu kompilátoru :
Operátor await jde použít jenom v asynchronní metodě. Zvažte označení této metody pomocí modifikátoru Async a změnu jejího návratového typu na Task.
Chcete-li získat hodnotu Title parametru v předchozím příkladu asynchronně, komponenta může použít OnInitializedAsync událost životního cyklu, jak ukazuje následující příklad:
<ParameterChild Title="@title" />
@code {
private string title;
protected override async Task OnInitializedAsync()
{
title = await ...;
}
}
Další informace naleznete v tématu RazorASP.NET Core životní cyklus komponenty.
Použití explicitního Razor výrazu k zřetězení textu s výsledkem výrazu pro přiřazení k parametru není podporováno. Následující příklad hledá zřetězení textu " Set by " s hodnotou vlastnosti objektu. I když je tato syntaxe podporována na Razor stránce ( .cshtml ), není platná pro přiřazení k Title parametru dítěte v součásti. Následující Razor syntaxe není podporována :
<ParameterChild Title="Set by @(panelData.Title)" />
Kód v předchozím příkladu generuje při sestavení aplikace chybu kompilátoru :
Atributy komponenty nepodporují složitý obsah (smíšený jazyk C# a označení).
Pro podporu přiřazení složené hodnoty použijte metodu, pole nebo vlastnost. Následující příklad provádí zřetězení " Set by " a hodnotu vlastnosti objektu v metodě jazyka C# GetTitle :
Pages/ParameterParent3.razor:
@page "/parameter-parent-3"
<ParameterChild Title="@GetTitle()" />
@code {
private PanelData panelData = new PanelData();
private string GetTitle() => $"Set by {panelData.Title}";
private class PanelData
{
public string Title { get; set; } = "Parent";
}
}
Další informace naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core.
Upozornění
Poskytování počátečních hodnot pro parametry součásti je podporováno, ale nevytvářejte komponentu, která zapisuje do vlastních parametrů po prvním vygenerování součásti. Další informace najdete v části přepsané parametry tohoto článku.
Parametry součásti by měly být deklarovány jako Automatické vlastnosti, což znamená, že by neměly obsahovat vlastní logiku ve svých get nebo přístupových sestavách set . Například následující StartData vlastnost je automatická vlastnost:
[Parameter]
public DateTime StartData { get; set; }
Neumísťujte vlastní logiku do get set přístupového objektu nebo, protože parametry komponenty jsou čistě určené pro použití jako kanál pro nadřazenou komponentu pro tok informací pro podřízenou komponentu. Pokud set přístupový objekt vlastnosti podřízené komponenty obsahuje logiku, která způsobí převykreslování nadřazené komponenty, výsledky smyčky nekonečného vykreslování.
Transformace přijaté hodnoty parametru:
- Ponechte vlastnost parametru jako automatickou vlastnost, která bude reprezentovat dodaná nezpracovaná data.
- Vytvořte jinou vlastnost nebo metodu pro poskytnutí transformovaných dat na základě vlastnosti parametru.
Přepište OnParametersSetAsync pro transformaci přijatého parametru pokaždé, když se přijímají nová data.
Zápis počáteční hodnoty do parametru komponenty je podporován, protože přiřazení počátečních hodnot nekoliduje s Blazor automatickým vykreslováním komponent. Následující přiřazení aktuální místní proměnné DateTime with DateTime.Now StartData je platnou syntaxí v součásti:
[Parameter]
public DateTime StartData { get; set; } = DateTime.Now;
Po počátečním přiřazení DateTime.Now nepřiřazujte hodnotu StartData v kódu pro vývojáře. Další informace najdete v části přepsané parametry tohoto článku.
Parametry směrování
Komponenty mohou určovat parametry směrování v šabloně směrování @page direktivy. Blazor Směrovač používá parametry směrování k naplnění odpovídajících parametrů komponent.
Pages/RouteParameter.razor:
@page "/route-parameter"
@page "/route-parameter/{text}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
Volitelné parametry směrování nejsou podporované, takže @page se v předchozím příkladu použijí dvě direktivy. První @page Direktiva umožňuje navigaci na součást bez parametru trasy. Druhá @page direktiva přijme {text} parametr Route a přiřadí hodnotu Text Vlastnosti.
Informace o zachycování všech parametrů tras ( {*pageRoute} ), které zachycují cesty mezi více hranicemi složek, naleznete v tématu ASP.NET Core Blazor úsek .
Přepsatelné parametry
BlazorRozhraní obecně ukládá bezpečné přiřazení parametrů z nadřazené na podřízený:
- Parametry nejsou neočekávaně přepsány.
- Vedlejší účinky jsou minimalizovány. Například další vykreslování se vyhne, protože mohou vytvářet nekonečné smyčky vykreslování.
Podřízená komponenta přijímá nové hodnoty parametrů, které mohou přepsat existující hodnoty při novém vykreslení nadřazené komponenty. Náhodné přepsání hodnot parametrů v podřízené komponentě se často objevuje při vývoji komponenty s jedním nebo více parametry svázanými s daty a vývojář přímo do parametru v podřízeném objektu:
- Podřízená komponenta je vykreslena s jednou nebo více hodnotami parametrů z nadřazené komponenty.
- Podřízené zápisy přímo k hodnotě parametru.
- Nadřazená komponenta se znovu vykreslí a přepíše hodnotu parametru dítěte.
Možnost přepisování hodnot parametrů se rozšíří i na přistupující objekty vlastnosti podřízené součásti set .
Důležité
Naše obecné pokyny neumožňují vytvářet komponenty, které přímo zapisují do vlastních parametrů po prvním vygenerování součásti.
Vezměte v úvahu následující vadnou Expander součást:
- Vykreslí podřízený obsah.
- Přepíná zobrazení podřízeného obsahu s parametrem součásti (
Expanded). - Komponenta zapisuje přímo do
Expandedparametru, který demonstruje problém s přepsanými parametry a je třeba se jim vyhnout.
Poté, co následující Expander Komponenta demonstruje nesprávný přístup k tomuto scénáři, Expander je zobrazena upravená součást k předvedení správného přístupu. Následující příklady můžete umístit do místní ukázkové aplikace a vyzkoušet si popsané chování.
Shared/Expander.razor:
<div @onclick="Toggle" class="card bg-light mb-3" style="width:30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code>Expanded</code> = @Expanded)</h2>
@if (Expanded)
{
<p class="card-text">@ChildContent</p>
}
</div>
</div>
@code {
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
private void Toggle()
{
Expanded = !Expanded;
}
}
ExpanderKomponenta je přidána do následující ExpanderExample nadřazené komponenty, která může zavolat StateHasChanged :
- Volání StateHasChanged v kódu pro vývojáře upozorní komponentu, jejíž stav byl změněn, a obvykle aktivuje opakované vykreslení komponenty pro aktualizaci uživatelského rozhraní. StateHasChanged je podrobněji popsán dále v částech RazorASP.NET Core životní cyklus komponenty a BlazorASP.NET Core vykreslování komponent .
@onclickAtribut direktivy tlačítka připojí obslužnou rutinu události konclickudálosti tlačítka. Zpracování událostí je podrobněji popsáno dále v ASP.NET Core Blazor zpracování událostí .
Pages/ExpanderExample.razor:
@page "/expander-example"
<Expander Expanded="true">
Expander 1 content
</Expander>
<Expander Expanded="true" />
<button @onclick="StateHasChanged">
Call StateHasChanged
</button>
Zpočátku se Expander komponenty chovají nezávisle při Expanded přepínání jejich vlastností. Podřízené komponenty udržují své stavy podle očekávání. Když StateHasChanged je volána v nadřazeném prvku, Expanded parametr první podřízené komponenty se obnoví zpět na původní hodnotu ( true ). Hodnota druhé Expander součásti Expanded není resetována, protože ve druhé komponentě není vykreslen žádný podřízený obsah.
Chcete-li zachovat stav v předchozím scénáři, použijte soukromé pole v Expander součásti k údržbě jeho přepnutého stavu.
Následující revidovaná Expander součást:
- Akceptuje
Expandedhodnotu parametru komponenty z nadřazené položky. - Přiřadí hodnotu parametru komponenty k soukromému poli (
expanded) vOnInitializedudálosti. - Používá soukromé pole k údržbě stavu přepínacího tlačítka, který ukazuje, jak se vyhnout zápisu přímo do parametru.
Poznámka
Rada v této části rozšiřuje na podobnou logiku v přístupových parametrech komponent set , což může vést k podobným nežádoucím vedlejším účinkům.
Shared/Expander.razor:
<div @onclick="Toggle" class="card bg-light mb-3" style="width:30rem">
<div class="card-body">
<h2 class="card-title">Toggle (<code>expanded</code> = @expanded)</h2>
@if (expanded)
{
<p class="card-text">@ChildContent</p>
}
</div>
</div>
@code {
private bool expanded;
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
protected override void OnInitialized()
{
expanded = Expanded;
}
private void Toggle()
{
expanded = !expanded;
}
}
Další informace najdete v tématu o Blazor dvou způsobech vazby – chyba (dotnet/aspnetcore #24599).
Podřízený obsah
Komponenty mohou nastavit obsah jiné součásti. Součást přiřazení poskytuje obsah mezi počátečními a ukončovacími značkami podřízené komponenty.
V následujícím příkladu RenderFragmentChild má komponenta ChildContent vlastnost, která představuje segment uživatelského rozhraní pro vykreslení jako RenderFragment . Pozice ChildContent v Razor kódu komponenty je místo, kde se obsah vykresluje v konečném výstupu HTML.
Shared/RenderFragmentChild.razor:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Child content</div>
<div class="card-body">@ChildContent</div>
</div>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
}
Důležité
Vlastnost, která přijímá RenderFragment obsah, musí být pojmenována ChildContent podle konvence.
Následující RenderFragmentParent Komponenta poskytuje obsah pro vykreslování RenderFragmentChild umístěním obsahu uvnitř značek pro otevírání a zavírání podřízené komponenty.
Pages/RenderFragmentParent.razor:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
Vzhledem k způsobu, jakým Blazor vykresluje podřízený obsah, vykreslování komponent uvnitř for smyčky vyžaduje proměnnou místního indexu, pokud se v obsahu komponenty používá proměnná přírůstkového cyklu RenderFragmentChild . Do předchozí součásti lze přidat následující příklad RenderFragmentParent :
<h1>Three children with an index variable</h1>
@for (int c = 0; c < 3; c++)
{
var current = c;
<RenderFragmentChild>
Count: @current
</RenderFragmentChild>
}
Alternativně použijte foreach smyčku Enumerable.Range místo for smyčky. Do předchozí součásti lze přidat následující příklad RenderFragmentParent :
<h1>Second example of three children with an index variable</h1>
@foreach (var c in Enumerable.Range(0,3))
{
<RenderFragmentChild>
Count: @c
</RenderFragmentChild>
}
Informace o tom, jak RenderFragment lze použít jako šablonu pro uživatelské rozhraní komponenty, najdete v následujících článcích:
Seskupováním atributů a libovolné parametry
Komponenty mohou kromě deklarovaných parametrů komponenty zachytit a vykreslovat další atributy. Další atributy mohou být zachyceny ve slovníku a poté splatted na prvek, když je komponenta vykreslena pomocí @attributes Razor atributu direktiva. Tento scénář je vhodný pro definování komponenty, která vytváří prvek značky, který podporuje nejrůznější přizpůsobení. Například může být zdlouhavé definovat atributy samostatně pro objekt <input> , který podporuje mnoho parametrů.
V následující Splat součásti:
- První
<input>prvek (id="useIndividualParams") používá parametry jednotlivých komponent. - Druhý
<input>element (id="useAttributesDict") používá atribut seskupováním.
Pages/Splat.razor:
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new Dictionary<string, object>()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
Vykreslené <input> prvky na webové stránce jsou identické:
<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
Chcete-li přijmout libovolné atributy, definujte parametr komponenty s CaptureUnmatchedValues vlastností nastavenou na true :
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> InputAttributes { get; set; }
}
CaptureUnmatchedValuesVlastnost on [Parameter] umožňuje, aby parametr odpovídal všem atributům, které se neshodují s žádným jiným parametrem. Komponenta může definovat pouze jeden parametr s CaptureUnmatchedValues . Typ vlastnosti používaný pomocí CaptureUnmatchedValues musí být přiřazovatelné z Dictionary<string, object> řetězcových klíčů. Použití IEnumerable<KeyValuePair<string, object>> nebo IReadOnlyDictionary<string, object> jsou také možnosti v tomto scénáři.
Pozice @attributes relativní vzhledem k poloze atributů elementu je důležitá. Když @attributes jsou splatted na elementu, atributy jsou zpracovávány zprava doleva (poslední až první). Vezměte v úvahu následující příklad nadřazené komponenty, která využívá podřízenou komponentu:
Shared/AttributeOrderChild1.razor:
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
Pages/AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
AttributeOrderChild1 extra Atribut komponenty je nastaven na hodnotu napravo od @attributes . AttributeOrderParent1Vykreslená komponenta <div> obsahuje extra="5" při předání prostřednictvím dodatečného atributu, protože atributy jsou zpracovávány zprava doleva (poslední až první):
<div extra="5" />
V následujícím příkladu extra je pořadí a @attributes obráceno v podřízené komponentě <div> :
Shared/AttributeOrderChild2.razor:
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
Pages/AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
<div>Webová stránka vykreslená v nadřazené komponentě obsahuje extra="10" při předání prostřednictvím dalšího atributu:
<div extra="10" />
Zachytit odkazy na komponenty
Odkazy na komponenty poskytují způsob, jak odkazovat na instanci komponenty pro vystavování příkazů. Zachytit odkaz na komponentu:
- Přidejte
@refatribut do podřízené součásti. - Definujte pole stejného typu jako podřízená komponenta.
Při vykreslení komponenty je pole vyplněno instancí součásti. Pak můžete vyvolat metody .NET v instanci.
Vezměte v úvahu následující ReferenceChild komponentu, která při volání zaznamená zprávu ChildMethod .
Shared/ReferenceChild.razor:
@using Microsoft.Extensions.Logging
@inject ILogger<ReferenceChild> logger
@code {
public void ChildMethod(int value)
{
logger.LogInformation("Received {Value} in ChildMethod", value);
}
}
Odkaz na komponentu je vyplněn až po vykreslení komponenty a jejího výstupu obsahuje ReferenceChild element. Dokud se komponenta nevykresluje, neexistuje žádný odkaz na.
Chcete-li pracovat s odkazy na součásti po dokončení vykreslování komponenty, použijte OnAfterRender OnAfterRenderAsync metody nebo.
Chcete-li použít referenční proměnnou s obslužnou rutinou události, použijte výraz lambda nebo přiřaďte delegáta obslužné rutiny události v OnAfterRender OnAfterRenderAsync metodách nebo. Tím se zajistí, že referenční proměnná je přiřazena před přiřazením obslužné rutiny události.
Následující přístup lambda používá předchozí ReferenceChild komponentu.
Pages/ReferenceParent1.razor:
@page "/reference-parent-1"
<button @onclick="@(() => childComponent.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
}
Následující přístup delegáta používá předchozí ReferenceChild komponentu.
Pages/ReferenceParent2.razor:
@page "/reference-parent-2"
<button @onclick="callChildMethod">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
private Action callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent.ChildMethod(5);
}
}
Použijte kolekci k odkazování na komponenty ve smyčce. V následujícím příkladu:
- Komponenty jsou přidány do List<T> .
- Je vytvořeno tlačítko pro každou komponentu, která spustí odpovídající komponentu
ChildMethodindex komponenty v List<T> .
Pages/ReferenceParent3.razor pomocí předchozí ReferenceChild komponenty:
@page "/reference-parent-3"
<ul>
@for (int i = 0; i < 5; i++)
{
var index = i;
var v = r.Next(1000);
<li>
<ReferenceChild @ref="childComponent" />
<button @onclick="@(() => callChildMethod(index, v))">
Component index @index: Call <code>ReferenceChild.ChildMethod(@v)</code>
</button>
</li>
}
</ul>
@code {
private Random r = new Random();
private List<ReferenceChild> components = new List<ReferenceChild>();
private Action<int, int> callChildMethod;
private ReferenceChild childComponent
{
set => components.Add(value);
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod(int index, int value)
{
components.ElementAt(index).ChildMethod(value);
}
}
Při zachytávání odkazů na součásti použijte podobnou syntaxi pro zachycení odkazů na prvky, zachycení odkazů na součásti není funkce interoperability JavaScriptu. Odkazy na součásti nejsou předány kódu jazyka JavaScript. Odkazy na komponenty se používají pouze v kódu .NET.
Důležité
Nepoužívejte odkazy na součásti pro použití stavu podřízených komponent. Místo toho použijte běžné deklarativní parametry komponenty k předání dat podřízeným součástem. Výsledkem použití parametrů komponenty jsou podřízené komponenty, které jsou automaticky revykreslovány ve správný čas. Další informace najdete v části parametry komponenty a v BlazorASP.NET Core datová vazba článku.
Kontext synchronizace
Blazor používá kontext synchronizace ( SynchronizationContext ) k vykonání jediného logického vlákna provádění. Metody životního cyklu komponenty a zpětná volání událostí, která vyvolala, Blazor jsou spouštěna v kontextu synchronizace.
Blazor Serverkontext synchronizace se pokouší emulovat prostředí s jedním vláknem tak, aby přesně odpovídal modelu webového sestavení v prohlížeči, který je jediným vláknem. V jakémkoli daném časovém okamžiku je práce prováděna v přesně jednom vlákně, což má za následek dojem jednoho logického vlákna. Žádné dvě operace se neprovádějí současně.
Vyhněte se voláním blokujícím vlákna
Obecně platí, že v součástech Nevolejte následující metody. Následující metody zablokují vlákno spouštění, takže aplikace brání v pokračování v práci, dokud se podklady Task nedokončí:
Poznámka
Blazor Příklady dokumentace, které používají metody blokující vlákna uvedené v této části, používají pouze metody pro demonstrační účely, nikoli doporučené pokyny pro kódování. Například několik ukázek kódu komponenty simuluje dlouhotrvající proces voláním Thread.Sleep .
Vyvolat metody komponenty externě na stav aktualizace
V případě, že komponenta musí být aktualizována na základě externí události, jako je například časovač nebo jiné oznámení, použijte InvokeAsync metodu, která odesílá kód pro spuštění Blazor v kontextu synchronizace. Zvažte například následující službu oznamovatele , která může oznámit všechny součásti naslouchání o aktualizovaném stavu. UpdateMetodu lze volat z libovolného místa v aplikaci.
TimerService.cs:
using System;
using System.Timers;
using Microsoft.Extensions.Logging;
public class TimerService : IDisposable
{
private int elapsedCount;
private readonly ILogger<TimerService> logger;
private readonly NotifierService notifier;
private Timer timer;
public TimerService(NotifierService notifier, ILogger<TimerService> logger)
{
this.notifier = notifier;
this.logger = logger;
}
public void Start()
{
if (timer is null)
{
timer = new();
timer.AutoReset = true;
timer.Interval = 10000;
timer.Elapsed += HandleTimer;
timer.Enabled = true;
logger.LogInformation("Started");
}
}
private async void HandleTimer(object source, ElapsedEventArgs e)
{
elapsedCount += 1;
await notifier.Update("elapsedCount", elapsedCount);
logger.LogInformation($"elapsedCount: {elapsedCount}");
}
public void Dispose()
{
timer?.Dispose();
}
}
NotifierService.cs:
using System;
using System.Threading.Tasks;
public class NotifierService
{
public async Task Update(string key, int value)
{
if (Notify != null)
{
await Notify.Invoke(key, value);
}
}
public event Func<string, int, Task> Notify;
}
Zaregistrujte služby:
V Blazor WebAssembly aplikaci zaregistrujte služby jako singleton v
Program.cs:builder.Services.AddSingleton<NotifierService>(); builder.Services.AddSingleton<TimerService>();V Blazor Server aplikaci zaregistrujte služby podle oboru v
Startup.ConfigureServices:services.AddScoped<NotifierService>(); services.AddScoped<TimerService>();
NotifierServiceK aktualizaci součásti použijte.
Pages/ReceiveNotifications.razor:
@page "/receive-notifications"
@implements IDisposable
@inject NotifierService Notifier
@inject TimerService Timer
<h1>Receive Notifications</h1>
<h2>Timer Service</h2>
<button @onclick="StartTimer">Start Timer</button>
<h2>Notifications</h2>
<p>
Status:
@if (lastNotification.key is not null)
{
<span>@lastNotification.key = @lastNotification.value</span>
}
else
{
<span>Awaiting first notification</span>
}
</p>
@code {
private (string key, int value) lastNotification;
protected override void OnInitialized()
{
Notifier.Notify += OnNotify;
}
public async Task OnNotify(string key, int value)
{
await InvokeAsync(() =>
{
lastNotification = (key, value);
StateHasChanged();
});
}
private void StartTimer()
{
Timer.Start();
}
public void Dispose()
{
Notifier.Notify -= OnNotify;
}
}
V předchozím příkladu:
NotifierServicevyvoláOnNotifymetodu komponenty mimo Blazor kontext synchronizace.InvokeAsyncslouží k přepnutí do správného kontextu a vykreslení vykreslování do fronty. Další informace naleznete v tématu BlazorASP.NET Core vykreslování komponent.- Komponenta implementuje IDisposable . U
OnNotifydelegáta jeDisposezrušena odběr metody, která je volána rozhraním, když je komponenta vyřazena. Další informace naleznete v tématu RazorASP.NET Core životní cyklus komponenty.
Slouží @key k řízení uchovávání prvků a komponent.
Při vykreslování seznamu prvků nebo komponent a prvků nebo komponent se následně Blazor musí rozhodnout, které z předchozích prvků nebo komponent mohou být zachovány a jakým způsobem by měly být namapovány objekty modelu. Obvykle je tento proces automatický a může být ignorován, ale existují případy, kdy můžete chtít řídit proces.
Vezměte v úvahu Details následující People komponenty a:
DetailsKomponenta přijímá data (Data) z nadřazenéPeoplekomponenty, která je zobrazena v<input>elementu. Kterýkoli zobrazený<input>element může obdržet fokus stránky od uživatele při výběru jednoho z<input>prvků.PeopleKomponenta vytvoří seznam objektů Person pro zobrazení pomocíDetailskomponenty. Každé tři sekundy se do kolekce přidá nová osoba.
Tato ukázka vám umožní:
- Vyberte
<input>mezi několika vykreslenýmiDetailskomponentami. - Prostudujte si chování fokusu stránky při automatickém zvětšování kolekce osob.
Shared/Details.razor:
<input value="@Data" />
@code {
[Parameter]
public string Data { get; set; }
}
V následující People součásti Každá iterace přidání osoby ve OnTimerCallback výsledku Blazor sestaví celou kolekci. Fokus stránky zůstává ve stejné pozici indexu <input> prvků, takže se fokus posune pokaždé, když je někdo přidaný. Přesunutí fokusu směrem od toho, co uživatel vybral, není žádoucí chování. Po demonstraci špatného chování s následující komponentou se @key pro zlepšení uživatelského prostředí používá atribut direktivy.
Pages/People.razor:
@page "/people"
@using System.Timers
@implements IDisposable
@foreach (var person in people)
{
<Details Data="@person.Data" />
}
@code {
private Timer timer = new Timer(3000);
public List<Person> people =
new List<Person>()
{
{ new Person { Data = "Person 1" } },
{ new Person { Data = "Person 2" } },
{ new Person { Data = "Person 3" } }
};
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
people.Insert(0,
new Person
{
Data = $"INSERTED {DateTime.Now.ToString("hh:mm:ss tt")}"
});
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
public class Person
{
public string Data { get; set; }
}
}
Obsah people kolekce se mění s vloženými, odstraněnými nebo znovu seřazenými položkami. Reprodukce může vést k viditelným rozdílům v chování. Pokaždé, když se do kolekce vloží osoba people , předchozí prvek aktuálně zaměřeného prvku dostane fokus. Dojde ke ztrátě fokusu uživatele.
Proces mapování elementů nebo komponent na kolekci lze řídit pomocí @key atributu direktiva. Použití @key zaručuje zachování prvků nebo komponent na základě hodnoty klíče. Pokud Details je komponenta v předchozím příkladu označena na person položce, Blazor ignoruje znovu Details součásti, které se nezměnily.
Chcete-li upravit People komponentu pro použití @key atributu direktiva v people kolekci, aktualizujte <Details> element na následující:
<Details @key="person" Data="@person.Data" />
Při people změně kolekce Details je zachováno přidružení mezi instancemi a person instancemi. Když Person je vložena na začátek kolekce, Details je do příslušné pozice vložena jedna nová instance. Ostatní instance zůstanou beze změny. Proto se fokus uživatele neztratí, protože se do kolekce přidávají uživatelé.
Další aktualizace kolekcí vykazují stejné chování při @key použití atributu direktiva:
- Pokud je instance odstraněna z kolekce, bude z uživatelského rozhraní odebrána pouze odpovídající instance komponenty. Ostatní instance zůstanou beze změny.
- Pokud jsou položky kolekce znovu seřazeny, odpovídající instance komponenty jsou zachovány a znovu uspořádány v uživatelském rozhraní.
Důležité
Klíče jsou místní pro každý prvek kontejneru nebo komponentu. Klíče nejsou v dokumentu globálně porovnány.
Kdy použít @key
Obvykle má smysl použít @key při každém vykreslení seznamu (například v foreach bloku) a existuje vhodná hodnota pro definování @key .
Můžete také použít @key k zachování elementu nebo podstromu komponenty, když se objekt nemění, jak ukazuje následující příklad.
Příklad 1:
<li @key="person">
<input value="@person.Data" />
</li>
Příklad 2:
<div @key="person">
@* other HTML elements *@
</div>
Pokud se person instance změní, @key direktiva atributu vynutí Blazor :
- Zahodí celé
<li>nebo<div>jeho následníky. - Vytvořte znovu podstrom v uživatelském rozhraní s novými prvky a komponentami.
To je užitečné, pokud chcete zaručit, že při změně kolekce v rámci podstromu dojde k zachování stavu uživatelského rozhraní.
Rozsah @key
@keyDirektiva atributu je v oboru nadřazeného prvku na stejné úrovni.
Představte si následující příklad. firstKlávesy a second jsou porovnány mezi sebou v rámci stejného oboru vnějšího <div> prvku:
<div>
<div @key="first">...</div>
<div @key="second">...</div>
</div>
Následující příklad ukazuje first klíče a second v jejich vlastních oborech, které vzájemně nesouvisejí a nemají vliv na sebe navzájem. Každý @key obor platí pouze pro svůj nadřazený <div> element, nikoli pro nadřazené <div> prvky:
<div>
<div @key="first">...</div>
</div>
<div>
<div @key="second">...</div>
</div>
Pro Details výše uvedenou součást následující příklady vykreslí person data v rámci stejného @key oboru a ukazují typické případy použití pro @key :
<div>
@foreach (var person in people)
{
<Details @key="person" Data="@person.Data" />
}
</div>
@foreach (var person in people)
{
<div @key="person">
<Details Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li @key="person">
<Details Data="@person.Data" />
</li>
}
</ol>
Následující příklady jsou pouze @key pro <div> <li> element nebo, který obklopuje jednotlivé Details instance komponenty. Proto person data pro každého člena people kolekce nejsou v jednotlivých person instancích ve vykreslených Details součástech. Při použití nástroje Vyhněte následujícím vzorům @key :
@foreach (var person in people)
{
<div>
<Details @key="person" Data="@person.Data" />
</div>
}
<ol>
@foreach (var person in people)
{
<li>
<Details @key="person" Data="@person.Data" />
</li>
}
</ol>
Kdy se nepoužívá @key
Při vykreslování se účtují náklady na výkon @key . Náklady na výkon nejsou velké, ale @key zachovají se jenom tehdy, když zachováte prvek nebo komponentu, které aplikace využívá.
I v případě @key , že není použit, Blazor zachová podřízený element a instance komponenty co nejvíce. Jedinou výhodou použití @key je řízení toho, jak jsou instance modelů mapovány na zachované instance komponent namísto Blazor výběru mapování.
Hodnoty, které se mají použít pro @key
Obecně dává smysl pro zadání jedné z následujících hodnot pro @key :
- Instance objektů modelu Například
Personinstance (person) byla použita v předchozím příkladu. To zajišťuje zachování v závislosti na rovnosti odkazů na objekty. - Jedinečné identifikátory. Jedinečné identifikátory můžou být například založené na hodnotách primárního klíče typu
int,stringneboGuid.
Zajistěte, aby hodnoty použité pro @key nekolidovat. Pokud jsou v rámci stejného nadřazeného prvku zjištěny hodnoty konfliktu, Blazor vyvolá výjimku, protože nemůže deterministické namapovat staré prvky nebo součásti na nové prvky nebo komponenty. Používejte pouze jedinečné hodnoty, například instance objektů nebo hodnoty primárního klíče.
Použití atributu
Atributy lze použít pro součásti s @attribute direktivou. Následující příklad používá [Authorize] atribut pro třídu komponenty:
@page "/"
@attribute [Authorize]
Podmíněné atributy elementu HTML
Vlastnosti atributu elementu HTML jsou podmíněně nastaveny v závislosti na hodnotě rozhraní .NET. Pokud je hodnota false nebo null , vlastnost není nastavena. Pokud je hodnota true , vlastnost je nastavena.
V následujícím příkladu určuje, IsCompleted zda <input> checked je nastavena vlastnost elementu.
Pages/ConditionalAttribute.razor:
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
Další informace naleznete v tématu RazorReferenční informace k syntaxi pro ASP.NET Core.
Upozornění
Některé atributy HTML, například aria-pressed , nefungují správně, pokud je typ .NET bool . V těchto případech použijte string typ místo typu bool .
Nezpracovaný kód HTML
Řetězce jsou obvykle vykreslovány pomocí textových uzlů modelu DOM, což znamená, že všechny značky, které mohou obsahovat, se ignorují a považují se za text literálu. Chcete-li vykreslit nezpracovaný kód HTML, zabalte obsah HTML do MarkupString hodnoty. Hodnota je analyzována jako HTML nebo SVG a vložena do modelu DOM.
Upozornění
Vykreslování nezpracovaného HTML vytvořeného z jakéhokoli nedůvěryhodného zdroje je bezpečnostní riziko a mělo by se vždy vyhnout.
Následující příklad ukazuje použití MarkupString typu pro přidání bloku statického obsahu HTML do vykresleného výstupu součásti.
Pages/MarkupStringExample.razor:
@page "/markup-string-example"
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
Razor šablony
Fragmenty vykreslování lze definovat pomocí Razor syntaxe šablony pro definování fragmentu uživatelského rozhraní. Razor šablony používají následující formát:
@<{HTML tag}>...</{HTML tag}>
Následující příklad ukazuje, jak zadat RenderFragment a RenderFragment<TValue> hodnoty a vykreslit šablony přímo v součásti. Fragmenty vykreslování mohou být také předány jako argumenty součástem šablon.
Pages/RazorTemplate.razor:
@page "/razor-template"
@timeTemplate
@petTemplate(new Pet { Name = "Nutty Rex" })
@code {
private RenderFragment timeTemplate = @<p>The time is @DateTime.Now.</p>;
private RenderFragment<Pet> petTemplate = (pet) => @<p>Pet: @pet.Name</p>;
private class Pet
{
public string Name { get; set; }
}
}
Vykreslený výstup předchozího kódu:
<p>The time is 4/19/2021 8:54:46 AM.</p>
<p>Pet: Nutty Rex</p>
Statické prostředky
Blazorpostupuje podle konvence ASP.NET Core aplikací pro statické prostředky. Statické prostředky se nacházejí ve web root wwwroot složce nebo složkách projektu ve wwwroot složce.
Použijte základní cestu ( / ) pro odkaz na webový kořenový adresář pro statický prostředek. V následujícím příkladu logo.png je fyzicky umístěný ve {PROJECT ROOT}/wwwroot/images složce. {PROJECT ROOT} je kořenový adresář projektu aplikace.
<img alt="Company logo" src="/images/logo.png" />
Komponenty nepodporují vlnové lomítko ( ~/ ).
Informace o nastavení základní cesty aplikace najdete v tématu Hostování a nasazení ASP.NET Core Blazor .
V součástech nejsou podporovány pomocníky značek.
Tag Helpers nepodporuje se v součástech. Chcete-li poskytnout funkci, jako je například Pomocník pro Blazor vytváření značek, vytvořte komponentu se stejnou funkcí jako pomocník značek a místo ní použijte komponentu.
Obrázky ve formátu SVG (Scalable Vector Graphics)
Vzhledem k tomu, že Blazor VYKRESLUJE HTML, obrázky podporované prohlížečem, včetně obrázků SVG (Scalable Vector Graphics) ( .svg ), jsou podporovány prostřednictvím <img> značky:
<img alt="Example image" src="image.svg" />
Podobně jsou obrázky SVG podporovány v pravidlech CSS souboru šablony stylů ( .css ):
.element-class {
background-image: url("image.svg");
}
Chování vykreslování prázdných znaků
Prázdný znak je uchováván v označení zdrojového kódu součásti. Prázdný text v DOM v prohlížeči se vykresluje i v případě, že neexistuje vizuální efekt.
Vezměte v úvahu následující značky komponenty:
<ul>
@foreach (var item in Items)
{
<li>
@item.Text
</li>
}
</ul>
Předchozí příklad vykreslí následující nepotřebné prázdné znaky:
- Mimo
@foreachblok kódu. - Kolem
<li>prvku. - Kolem
@item.Textvýstupu.
Seznam 100 položek má za následek více než 400 oblastí prázdných znaků. Žádné nadbytečné prázdné znaky vizuálně neovlivní Vykreslený výstup.
Při vykreslování statického HTML pro součásti se nezachovají prázdné znaky uvnitř značky. Můžete například zobrazit Vykreslený výstup následující <img> značky v Razor souboru komponenty ( .razor ):
<img alt="Example image" src="img.png" />
Mezera není zachována z předchozí značky:
<img alt="Example image" src="img.png" />
Podpora parametrů obecného typu
@typeparamDirektiva deklaruje parametr obecného typu pro generovanou třídu komponenty:
@typeparam TItem
Další informace najdete v následujících článcích: