Komponenty ASP.NET Core Razor
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Tento článek vysvětluje, jak vytvářet a používat komponenty Razor v aplikacích Blazor, a obsahuje doprovodné materiály k syntaxi Razor, pojmenování komponent, oborům názvů a parametrům komponent.
Komponenty Razor
Blazoraplikace se vytvářejí pomocí Razor komponent, které se neformálně označují jakoBlazorkomponenty nebo pouze komponenty. Komponenta je samostatná část uživatelského rozhraní s logikou zpracování, která umožňuje dynamické chování. Komponenty se dají vnořit, opakovaně používat, sdílet mezi projekty a používat v aplikacích MVC a Razor Pages.
Komponenty se vykreslují do reprezentace modelu DOM (Document Object Model) prohlížeče označovaného jako vykreslovací strom, který se používá k aktualizaci uživatelského rozhraní flexibilním a efektivním způsobem.
I když "Razor komponenty" sdílejí některé názvy s jinými technologiemi pro vykreslování obsahu ASP.NET Core, Razor komponenty musí být odlišeny od následujících různých funkcí v ASP.NET Core:
- Razor zobrazení, která jsou Razorzaložená na značkových stránkách pro aplikace MVC.
- Umožňuje zobrazit komponenty, které slouží k vykreslování bloků obsahu místo celých odpovědí v Razor aplikacích Pages a MVC.
Důležité
Při použití Blazor Web App, většina ukázkových Blazor komponent dokumentace vyžaduje interaktivitu k fungování a předvedení konceptů popsaných v článcích. Při testování ukázkové komponenty poskytované článkem se ujistěte, že aplikace přijme globální interaktivitu nebo komponenta přijme interaktivní režim vykreslování. Další informace o tomto tématu poskytují Blazor vykreslování ASP.NET Core, což je další článek v obsahu po tomto článku.
Třídy komponent
Komponenty se implementují s využitím kombinace kódu jazyka C# a HTML v souborech komponent Razor s příponou .razor
.
ComponentBase je základní třída komponent popsaných soubory Razor komponent. ComponentBase implementuje nejnižší abstrakci komponent, IComponent rozhraní. ComponentBase definuje vlastnosti a metody komponent pro základní funkce, například ke zpracování sady předdefinovaných událostí životního cyklu součástí.
ComponentBase
v dotnet/aspnetcore
referenčním zdroji: Referenční zdroj obsahuje další poznámky k integrovaným událostem životního cyklu. Mějte však na paměti, že interní implementace funkcí komponent se můžou kdykoli změnit bez předchozího upozornění.
Poznámka:
Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Vývojáři obvykle vytvářejí Razor komponenty ze Razor souborů komponent (.razor
) nebo zakládají své součásti na ComponentBase, ale komponenty lze také sestavit implementací IComponent. Komponenty vytvořené vývojářem, které implementují IComponent , můžou mít kontrolu nad vykreslováním nízké úrovně za cenu ruční aktivace vykreslování pomocí událostí a metod životního cyklu, které musí vývojář vytvořit a udržovat.
Další konvence přijaté ukázkovým kódem Blazor dokumentace a ukázkovými aplikacemi najdete v základních ASP.NET CoreBlazor.
Syntaxe Razor
Komponenty používají syntaxi Razor. Komponenty hojně využívají dva prvky Razor, direktivy a atributy direktiv. Jedná se o vyhrazená klíčová slova s předponou @
, která se objevují v kódu Razor:
Direktivy: Změna způsobu kompilace značek komponent nebo funkcí Například direktiva
@page
určuje směrovatelnou komponentu se šablonou trasy, ke které může uživatel požádat přímo v prohlížeči na konkrétní adresu URL.Direktivy komponenty v horní části definice komponenty (
.razor
souboru) jsou podle konvence umístěny v konzistentním pořadí. Pro opakované direktivy jsou direktivy umístěny abecedně podle oboru názvů nebo typu, s výjimkou@using
direktiv, které mají zvláštní pořadí druhé úrovně.Ukázkové aplikace a dokumentace přijímají Blazor následující pořadí. Komponenty poskytované šablonou Blazor projektu se můžou lišit od následujícího pořadí a používají jiný formát. Komponenty architektury Blazor například Identity obsahují prázdné řádky mezi bloky
@using
direktiv a bloků@inject
direktiv. Ve svých vlastních aplikacích můžete používat vlastní schéma řazení a formát.Dokumentace a pořadí direktiv ukázkové aplikace Razor :
@page
-
@rendermode
(.NET 8 nebo novější) @using
-
System
obory názvů (abecední pořadí) -
Microsoft
obory názvů (abecední pořadí) - Obory názvů rozhraní API třetích stran (abecední pořadí)
- Obory názvů aplikací (abecední pořadí)
-
- Jiné direktivy (abecední pořadí)
Mezi direktivami se nezobrazují žádné prázdné řádky. Jeden prázdný řádek se zobrazí mezi direktivou a prvním řádkem Razor značek.
Příklad:
@page "/doctor-who-episodes/{season:int}" @rendermode InteractiveWebAssembly @using System.Globalization @using System.Text.Json @using Microsoft.AspNetCore.Localization @using Mandrill @using BlazorSample.Components.Layout @attribute [Authorize] @implements IAsyncDisposable @inject IJSRuntime JS @inject ILogger<DoctorWhoEpisodes> Logger <PageTitle>Doctor Who Episode List</PageTitle> ...
Atributy direktiv: Změna způsobu kompilace elementu komponenty nebo funkcí.
Příklad:
<input @bind="episodeId" />
Hodnoty atributů direktivy můžete předponovat pomocí symbolu at (
@
) pro ne explicitní Razor výrazy (@bind="@episodeId"
), ale nedoporučujeme je a dokumenty nepřijímají přístup v příkladech.
Podrobnější vysvětlení direktiv a atributů direktiv najdete v tomto článku a v dalších článcích dokumentace k architektuře Blazor. Obecné informace o syntaxi Razor najdete v referenčních informacích k syntaxi Razor pro ASP.NET Core.
Název komponenty, název třídy a obor názvů
Název komponenty musí začínat velkým písmenem:
Podporovaný:ProductDetail.razor
Nepodporovaný:productDetail.razor
Mezi běžné zásady vytváření názvů Blazor používané v dokumentaci k architektuře Blazor patří:
- Cesty k souborům a názvy souborů používají písmena Pascal† a před zobrazením příkladů kódu se zobrazí. Pokud je k dispozici cesta, označuje typické umístění složky. Označuje například,
Components/Pages/ProductDetail.razor
žeProductDetail
komponenta má názevProductDetail.razor
souboru a nachází se vePages
složceComponents
složky aplikace. - Cesty k souborům komponent pro směrovatelné komponenty odpovídají jejich adresám URL v případě kebabu s pomlčkami, které se zobrazují mezi slovy v šabloně trasy komponenty. Například komponenta
ProductDetail
s šablonou trasy/product-detail
(@page "/product-detail"
) je přístupná v prohlížeči na relativní adrese URL/product-detail
.
† PascalCase (UpperCamelCase) je konvence vytváření názvů bez mezer a interpunkce a s velkým počátečním písmenem každého slova, včetně prvního.
{Kebab case je konvence pojmenování bez mezer a interpunkce, která používá malá písmena a pomlčky mezi slovy.
Komponenty jsou běžné třídy jazyka C#, které je možné umístit kdekoli v rámci projektu. Komponenty, které generují webové stránky, se obvykle nacházejí ve složce Components/Pages
. Komponenty, které negenerují stránky, se často umisťují do složky Components
nebo vlastní složky přidané do projektu.
Obor názvů komponenty se obvykle odvozuje od kořenového oboru názvů aplikace a umístění (složky) komponenty v rámci aplikace. Pokud je kořenový obor názvů aplikace BlazorSample
a komponenta Counter
se nachází ve složce Components/Pages
:
- Obor názvů komponenty
Counter
jeBlazorSample.Components.Pages
. - Plně kvalifikovaný název typu komponenty je
BlazorSample.Components.Pages.Counter
.
V případě vlastních složek s komponentami přidejte do nadřazené komponenty nebo souboru @using
aplikace direktivu _Imports.razor
. Následující příklad zpřístupní komponenty ve složce AdminComponents
:
@using BlazorSample.AdminComponents
Poznámka:
Direktivy @using
v souboru _Imports.razor
se vztahují pouze na soubory Razor (.razor
), nikoli na soubory jazyka C# (.cs
).
Podporují se příkazy aliasů using
. V následujícím příkladu je veřejná WeatherForecast
třída GridRendering
komponenty zpřístupněna jako WeatherForecast
součást jinde v aplikaci:
@using WeatherForecast = Components.Pages.GridRendering.WeatherForecast
Na komponenty je také možné odkazovat pomocí jejich plně kvalifikovaných názvu, k čemuž se direktiva @using
nevyžaduje. Následující příklad přímo odkazuje na komponentu ProductDetail
ve složce AdminComponents/Pages
aplikace:
<BlazorSample.AdminComponents.Pages.ProductDetail />
Obor názvů komponenty vytvořené pomocí Razor vychází z následujících prvků (v pořadí podle priority):
- Direktiva
@namespace
v kódu souboru Razor (například@namespace BlazorSample.CustomNamespace
). - Kořenový obor názvů (
RootNamespace
) projektu v souboru projektu (například<RootNamespace>BlazorSample</RootNamespace>
). - Obor názvů projektu a cesta z kořenového adresáře projektu do komponenty. Architektura se například překládá
{PROJECT NAMESPACE}/Components/Pages/Home.razor
s oborem názvů projektu oboru názvůBlazorSample
BlazorSample.Components.Pages
pro komponentuHome
.{PROJECT NAMESPACE}
je obor názvů projektu. Komponenty dodržují pravidla vazby názvů jazyka C#. Pro komponentuHome
v tomto příkladu jsou všechny komponenty v oboru:- Komponenty ve stejné složce
Components/Pages
- Komponenty v kořenovém adresáři projektu, které nemají explicitně zadaný jiný obor názvů
- Komponenty ve stejné složce
Následující se nepodporuje:
- Kvalifikace
global::
. - Částečně kvalifikované názvy. Například není možné do komponenty přidat
@using BlazorSample.Components
a pak na komponentuNavMenu
ve složceComponents/Layout
aplikace (Components/Layout/NavMenu.razor
) odkazovat pomocí<Layout.NavMenu></Layout.NavMenu>
.
Název komponenty musí začínat velkým písmenem:
Podporovaný:ProductDetail.razor
Nepodporovaný:productDetail.razor
Mezi běžné zásady vytváření názvů Blazor používané v dokumentaci k architektuře Blazor patří:
- Cesty k souborům a názvy souborů používají písmena Pascal† a před zobrazením příkladů kódu se zobrazí. Pokud je k dispozici cesta, označuje typické umístění složky. Například cesta
Pages/ProductDetail.razor
značí, že soubor komponentyProductDetail
má názevProductDetail.razor
a nachází se ve složcePages
aplikace. - Cesty k souborům komponent pro směrovatelné komponenty odpovídají jejich adresám URL v případě kebabu s pomlčkami, které se zobrazují mezi slovy v šabloně trasy komponenty. Například komponenta
ProductDetail
s šablonou trasy/product-detail
(@page "/product-detail"
) je přístupná v prohlížeči na relativní adrese URL/product-detail
.
† PascalCase (UpperCamelCase) je konvence vytváření názvů bez mezer a interpunkce a s velkým počátečním písmenem každého slova, včetně prvního.
{Kebab case je konvence pojmenování bez mezer a interpunkce, která používá malá písmena a pomlčky mezi slovy.
Komponenty jsou běžné třídy jazyka C#, které je možné umístit kdekoli v rámci projektu. Komponenty, které generují webové stránky, se obvykle nacházejí ve složce Pages
. Komponenty, které negenerují stránky, se často umisťují do složky Shared
nebo vlastní složky přidané do projektu.
Obor názvů komponenty se obvykle odvozuje od kořenového oboru názvů aplikace a umístění (složky) komponenty v rámci aplikace. Pokud je kořenový obor názvů aplikace BlazorSample
a komponenta Counter
se nachází ve složce Pages
:
- Obor názvů komponenty
Counter
jeBlazorSample.Pages
. - Plně kvalifikovaný název typu komponenty je
BlazorSample.Pages.Counter
.
V případě vlastních složek s komponentami přidejte do nadřazené komponenty nebo souboru @using
aplikace direktivu _Imports.razor
. Následující příklad zpřístupní komponenty ve složce AdminComponents
:
@using BlazorSample.AdminComponents
Poznámka:
Direktivy @using
v souboru _Imports.razor
se vztahují pouze na soubory Razor (.razor
), nikoli na soubory jazyka C# (.cs
).
Podporují se příkazy aliasů using
. V následujícím příkladu je veřejná WeatherForecast
třída GridRendering
komponenty zpřístupněna jako WeatherForecast
součást jinde v aplikaci:
@using WeatherForecast = Pages.GridRendering.WeatherForecast
Na komponenty je také možné odkazovat pomocí jejich plně kvalifikovaných názvu, k čemuž se direktiva @using
nevyžaduje. Následující příklad přímo odkazuje na komponentu ProductDetail
ve složce Components
aplikace:
<BlazorSample.Components.ProductDetail />
Obor názvů komponenty vytvořené pomocí Razor vychází z následujících prvků (v pořadí podle priority):
- Direktiva
@namespace
v kódu souboru Razor (například@namespace BlazorSample.CustomNamespace
). - Kořenový obor názvů (
RootNamespace
) projektu v souboru projektu (například<RootNamespace>BlazorSample</RootNamespace>
). - Obor názvů projektu a cesta z kořenového adresáře projektu do komponenty. Architektura se například překládá
{PROJECT NAMESPACE}/Pages/Index.razor
s oborem názvů projektu oboru názvůBlazorSample
BlazorSample.Pages
pro komponentuIndex
.{PROJECT NAMESPACE}
je obor názvů projektu. Komponenty dodržují pravidla vazby názvů jazyka C#. Pro komponentuIndex
v tomto příkladu jsou všechny komponenty v oboru:- Komponenty ve stejné složce
Pages
- Komponenty v kořenovém adresáři projektu, které nemají explicitně zadaný jiný obor názvů
- Komponenty ve stejné složce
Následující se nepodporuje:
- Kvalifikace
global::
. - Částečně kvalifikované názvy. Například není možné do komponenty přidat
@using BlazorSample
a pak na komponentuNavMenu
ve složceShared
aplikace (Shared/NavMenu.razor
) odkazovat pomocí<Shared.NavMenu></Shared.NavMenu>
.
Podpora dílčích tříd
Komponenty se generují jako dílčí třídy jazyka C# a vytváří se následujícími způsoby:
- Jeden soubor obsahuje kód jazyka C# definovaný v jednom nebo více blocích
@code
, kódu HTML a kódu Razor. Tento přístup s jedním souborem se používá k definování komponent v šablonách projektů Blazor. - Kód HTML a Razor se umístí do souboru Razor (
.razor
). Kód jazyka C# se umístí do souboru kódu definovaného jako dílčí třída (.cs
).
Poznámka:
Šablona stylů komponenty, která definuje styly specifické pro komponentu, se nachází v samostatném souboru (.css
). Izolace šablon stylů CSS v architektuře Blazor je popsaná dále v tématu Izolace šablon stylů CSS v ASP.NET Core Blazor.
Následující příklad ukazuje výchozí komponentu Counter
s blokem @code
v aplikaci vygenerované z šablony projektu Blazor. Kód HTML a jazyka C# se nachází ve stejném souboru. Tento přístup se při vytváření komponent používá nejčastěji.
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++;
}
@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++;
}
@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++;
}
}
@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++;
}
}
@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++;
}
}
@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 prezentace a Razor značky z kódu C# pomocí souboru kódu za kódem s částečnou třídou. Rozdělení kódu z kódu jazyka C# je upřednostňováno některými organizacemi a vývojáři, aby uspořádali kód komponenty tak, aby vyhovoval tomu, jak preferují práci. Odborník na uživatelské rozhraní organizace může například pracovat na prezentační vrstvě nezávisle na jiném vývojáři pracujícím na logice C# komponenty. Tento přístup je také užitečný při práci s automaticky generovaným kódem nebo generátory zdrojů. Další informace naleznete v části Částečné třídy a metody (Průvodce programováním v C#).
CounterPartialClass.razor
:
@page "/counter-partial-class"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
CounterPartialClass.razor.cs
:
namespace BlazorSample.Components.Pages;
public partial class CounterPartialClass
{
private int currentCount = 0;
private void IncrementCount() => currentCount++;
}
namespace BlazorSample.Components.Pages;
public partial class CounterPartialClass
{
private int currentCount = 0;
private void IncrementCount() => currentCount++;
}
namespace BlazorSample.Pages;
public partial class CounterPartialClass
{
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
namespace BlazorSample.Pages
{
public partial class CounterPartialClass
{
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
}
Direktivy @using
v souboru _Imports.razor
se vztahují pouze na soubory Razor (.razor
), nikoli na soubory jazyka C# (.cs
). Podle potřeby můžete do souboru dílčí třídy přidat další obory názvů.
Obory názvů obvykle používané komponentami:
using System.Net.Http;
using System.Net.Http.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Sections
using Microsoft.AspNetCore.Components.Web;
using static Microsoft.AspNetCore.Components.Web.RenderMode;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
Mezi obvyklé obory názvů patří také obor názvů aplikace a obor názvů odpovídající složce Components
aplikace:
using BlazorSample;
using BlazorSample.Components;
Můžete také zahrnout další složky, například Layout
složku:
using BlazorSample.Components.Layout;
using System.Net.Http;
using System.Net.Http.Json;
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;
Mezi obvyklé obory názvů patří také obor názvů aplikace a obor názvů odpovídající složce Shared
aplikace:
using BlazorSample;
using BlazorSample.Shared;
using System.Net.Http;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
Mezi obvyklé obory názvů patří 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
K určení základní třídy komponenty slouží direktiva @inherits
. Na rozdíl od použití částečných tříd, které rozdělují pouze značky z logiky jazyka C#, umožňuje použití kódu jazyka C# ve skupině komponent, které sdílejí vlastnosti a metody základní třídy. Použití základních tříd snižuje redundanci kódu v aplikacích a je užitečné při zadávání základního kódu z knihoven tříd do více aplikací. Další informace najdete v tématu Dědičnost v jazyce C# a .NET.
V následujícím příkladu BlazorRocksBase1
základní třída je odvozena z ComponentBase.
BlazorRocks1.razor
:
@page "/blazor-rocks-1"
@inherits BlazorRocksBase1
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 1</h1>
<p>
@BlazorRocksText
</p>
@page "/blazor-rocks-1"
@inherits BlazorRocksBase1
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 1</h1>
<p>
@BlazorRocksText
</p>
@page "/blazor-rocks-1"
@inherits BlazorRocksBase1
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 1</h1>
<p>
@BlazorRocksText
</p>
@page "/blazor-rocks-1"
@inherits BlazorRocksBase1
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 1</h1>
<p>
@BlazorRocksText
</p>
@page "/blazor-rocks-1"
@inherits BlazorRocksBase1
<h1>Blazor Rocks! Example 1</h1>
<p>
@BlazorRocksText
</p>
@page "/blazor-rocks-1"
@inherits BlazorRocksBase1
<h1>Blazor Rocks! Example 1</h1>
<p>
@BlazorRocksText
</p>
BlazorRocksBase1.cs
:
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase1 : ComponentBase
{
public string BlazorRocksText { get; set; } = "Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase1 : ComponentBase
{
public string BlazorRocksText { get; set; } = "Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase1 : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase1 : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase1 : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase1 : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
Směrování
Směrování v architektuře Blazor se zajišťuje zadáním šablony trasy ke každé přístupné komponentě v aplikaci pomocí direktivy @page
. Když se vygeneruje soubor Razor s direktivou @page
, vygenerované třídě se přidělí atribut RouteAttribute s šablonou trasy. Za běhu směrovač prohledá třídy komponent s atributem RouteAttribute a vykreslí komponentu s šablonou trasy, která odpovídá požadované adrese URL.
Následující HelloWorld
komponenta používá šablonu /hello-world
trasy a vykreslená webová stránka pro komponentu je dosažena na relativní adrese URL /hello-world
.
HelloWorld.razor
:
@page "/hello-world"
<PageTitle>Hello World!</PageTitle>
<h1>Hello World!</h1>
@page "/hello-world"
<PageTitle>Hello World!</PageTitle>
<h1>Hello World!</h1>
@page "/hello-world"
<h1>Hello World!</h1>
@page "/hello-world"
<h1>Hello World!</h1>
@page "/hello-world"
<h1>Hello World!</h1>
@page "/hello-world"
<h1>Hello World!</h1>
Výše uvedená komponenta se v prohlížeči načte na adrese /hello-world
bez ohledu na to, jestli ji přidáte do navigace v uživatelském rozhraní aplikace. Komponenty je volitelně možné přidat do komponenty NavMenu
, aby se v navigaci v uživatelském rozhraní aplikace zobrazil odkaz na komponentu.
Pro předchozí HelloWorld
komponentu můžete do komponenty přidat komponentu NavLink
NavMenu
. Další informace, včetně popisu komponent NavLink
a NavMenu
, najdete v tématu Směrování a navigace v ASP.NET Core Blazor.
Značkování
Uživatelské rozhraní komponenty se definuje pomocí syntaxe Razor, která se skládá z kódu Razor, jazyka C# a HTML. Při kompilaci aplikace se kód HTML a logika vykreslování jazyka C# převedou na třídu komponenty. Název vygenerované třídy odpovídá názvu souboru.
Členové třídy komponenty se definují v jednom nebo více blocích @code
. V blocích @code
se pomocí jazyka C# určuje a zpracovává stav komponenty:
- Inicializátory vlastností a polí
- Hodnoty parametrů z argumentů předaných nadřazenými komponentami a parametry trasy
- Metody pro zpracování uživatelských událostí, událostí životního cyklu a vlastní logiky komponenty
Členové komponenty se používají v logice vykreslování pomocí výrazů jazyka C#, které začínají symbolem @
. Například pole jazyka C# se vykreslí přidáním předpony @
k názvu pole. Následující komponenta Markup
vyhodnotí a vykreslí:
-
headingFontStyle
pro hodnotu vlastnosti CSSfont-style
elementu nadpisu -
headingText
pro obsah elementu nadpisu
Markup.razor
:
@page "/markup"
<PageTitle>Markup</PageTitle>
<h1>Markup Example</h1>
<h2 style="font-style:@headingFontStyle">@headingText</h2>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
@page "/markup"
<PageTitle>Markup</PageTitle>
<h1>Markup Example</h1>
<h2 style="font-style:@headingFontStyle">@headingText</h2>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
@page "/markup"
<h1 style="font-style:@headingFontStyle">@headingText</h1>
@code {
private string headingFontStyle = "italic";
private string headingText = "Put on your new Blazor!";
}
Poznámka:
V příkladech v dokumentaci k architektuře Blazor se pro privátní členy určuje modifikátor přístupu private
. Privátní členové mají obor vymezený na třídu komponenty. V jazyce C# však platí, že pokud není zadaný žádný modifikátor přístupu, použije se modifikátor přístupu private
, takže explicitní označení členů v kódu modifikátorem přístupu private
je volitelné. Další informace o modifikátorech přístupu najdete v tématu Modifikátory přístupu (Průvodce programováním v jazyce C#).
Architektura Blazor interně zpracovává komponentu jako strom vykreslování, což je kombinace modelu MODELU DOM komponenty a modelu CSSOM (Cascading Style Sheet Object Model). Po počátečním vykreslení komponenty se strom vykreslování komponenty generuje znovu v reakci na události. Blazor porovná nový strom vykreslování s předchozím stromem vykreslování a prostřednictvím modelu DOM prohlížeče zobrazí všechny úpravy. Další informace najdete v tématu Vykreslování komponent ASP.NET Core Razor.
V syntaxi Razor jsou řídicí struktury, direktivy a atributy direktiv jazyka C# malými písmeny (příklady: @if
, @code
, @bind
). Názvy vlastností jsou velkými písmeny (příklad: @Body
nebo LayoutComponentBase.Body).
Asynchronní metody (async
) nepodporují návratovou hodnotu void
Architektura Blazor nesleduje asynchronní metody vracející hodnotu void
(async
). Proto se v případě vrácení hodnoty void
nezachytí výjimka. Asynchronní metody musí vždy vracet objekt Task.
Vnořené komponenty
Komponenty můžou zahrnovat další komponenty deklarované pomocí syntaxe HTML. Kód pro použití komponenty vypadá jako značka HTML, kde název značky představuje typ komponenty.
Podívejte se například na následující komponentu Heading
, pomocí které můžou další komponenty zobrazit nadpis.
Heading.razor
:
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
<h1 style="font-style:@headingFontStyle">Heading Example</h1>
@code {
private string headingFontStyle = "italic";
}
Následující kód v komponentě HeadingExample
vykreslí výše uvedenou komponentu Heading
v místě, kde se nachází značka <Heading />
.
HeadingExample.razor
:
@page "/heading-example"
<PageTitle>Heading</PageTitle>
<h1>Heading Example</h1>
<Heading />
@page "/heading-example"
<PageTitle>Heading</PageTitle>
<h1>Heading Example</h1>
<Heading />
@page "/heading-example"
<Heading />
@page "/heading-example"
<Heading />
@page "/heading-example"
<Heading />
@page "/heading-example"
<Heading />
Pokud komponenta obsahuje element HTML s velkým počátečním písmenem, který neodpovídá názvu žádné komponenty ve stejném oboru názvů, vygeneruje se upozornění na neočekávaný název elementu. Přidáním direktivy @using
s oborem názvů komponenty se komponenta zpřístupní a upozornění se vyřeší. Další informace naleznete v části Název komponenty, název třídy a obor názvů .
Příklad komponenty Heading
uvedený v této části neobsahuje direktivu @page
, takže uživatel ke komponentě Heading
nemá přímý přístup přes přímý požadavek v prohlížeči. Jakoukoli komponentu s direktivou @page
je však možné vnořit do jiné komponenty. Kdyby na začátku souboru Heading
komponenty @page "/heading"
byla direktiva Razor a komponenta tak byla přímo přístupná, vykreslila by se v prohlížeči při požadavcích na /heading
i /heading-example
.
Parametry komponent
Parametry komponent předávají data do komponent a definují se pomocí veřejných vlastností jazyka C# v třídě komponenty pomocí atributu [Parameter]
. V následujícím příkladu se jako parametry komponenty předávají předdefinovaný odkazový typ (System.String) a odkazový typ definovaný uživatelem (PanelBody
).
PanelBody.cs
:
namespace BlazorSample;
public class PanelBody
{
public string? Text { get; set; }
public string? Style { get; set; }
}
namespace BlazorSample;
public class PanelBody
{
public string? Text { get; set; }
public string? Style { get; set; }
}
public class PanelBody
{
public string? Text { get; set; }
public string? Style { get; set; }
}
public class PanelBody
{
public string? Text { get; set; }
public string? Style { get; set; }
}
public class PanelBody
{
public string Text { get; set; }
public string Style { get; set; }
}
public class PanelBody
{
public string Text { get; set; }
public string Style { get; set; }
}
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 = "Card content set by child.",
Style = "normal"
};
}
<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 = "Card content set by child.",
Style = "normal"
};
}
<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"
};
}
<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"
};
}
<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"
};
}
<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"
};
}
Upozorňující
Zadání počátečních hodnot parametrů komponent se podporuje, ale nevytvářejte komponenty, které po prvotním vykreslení zapisují do vlastních parametrů. Další informace naleznete v tématu Vyhněte se přepsání parametrů v ASP.NET Core Blazor.
Parametry Title
a Body
komponenty ParameterChild
se nastavují argumenty ve značce HTML, která vykreslí instanci komponenty. Následující komponenta ParameterParent
vykreslí dvě komponenty ParameterChild
:
- První komponenta
ParameterChild
se vykreslí bez zadání argumentů parametrů. - Druhá komponenta
ParameterChild
přijímá hodnoty parametrůTitle
aBody
z komponentyParameterParent
, která k nastavení hodnot vlastností používáPanelBody
.
Parameter1.razor
:
@page "/parameter-1"
<PageTitle>Parameter 1</PageTitle>
<h1>Parameter Example 1</h1>
<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" })" />
Parameter1.razor
:
@page "/parameter-1"
<PageTitle>Parameter 1</PageTitle>
<h1>Parameter Example 1</h1>
<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" })" />
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" })" />
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" })" />
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" })" />
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" })" />
V následujícím vykresleném kódu HTML z komponenty ParameterParent
se zobrazí výchozí hodnoty komponenty ParameterChild
, když se nezadají hodnoty parametrů komponenty ParameterParent
. Pokud se pro komponentu ParameterParent
zadají hodnoty parametrů komponenty, nahradí výchozí hodnoty komponenty ParameterChild
.
Poznámka:
Kvůli přehlednosti se v následujícím vykresleném kódu HTML nezobrazují vykreslené třídy stylů CSS.
<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 parametru komponenty jako hodnotu atributu HTML. Hodnota atributu může být obvykle libovolný výraz jazyka C#, který odpovídá typu parametru. Hodnota atributu může volitelně vést rezervovaným Razor@
symbolem, ale nevyžaduje se.
Pokud je parametr komponenty typu řetězec, hodnota atributu se místo toho považuje za řetězcový literál jazyka C#. Pokud chcete místo toho zadat výraz jazyka C#, použijte předponu @
.
Následující komponenta ParameterParent2
zobrazí čtyři instance výše uvedené komponenty ParameterChild
a nastaví jejich parametr Title
na následující hodnoty:
- Hodnota pole
title
- Výsledek metody
GetTitle
jazyka C# - Aktuální místní datum v dlouhém formátu pomocí metody ToLongDateString, která používá implicitní výraz jazyka C#
- Vlastnost
panelData
objektuTitle
Uvozovky kolem hodnot atributů parametrů jsou podle specifikace HTML5 ve většině případů volitelné. Například místo Value=this
můžete použít Value="this"
. Doporučujeme však uvozovky používat, protože je to jednodušší na zapamatování a široce rozšířené napříč webovými technologiemi.
Pro příklady kódu v dokumentaci platí následující:
- Vždy se používají uvozovky. Příklad:
Value="this"
. - Nepoužívejte předponu
@
s neliteraly, pokud není vyžadována. Příklad:Count="ct"
, kdect
je proměnná typu číslo.Count="@ct"
je platný stylistický přístup, ale dokumentace a příklady tuto konvenci nepřijímají. - Vždy se vyhněte
@
literálům mimo Razor výrazy. Příklad:IsFixed="true"
. To zahrnuje klíčová slova (napříkladthis
) anull
, ale pokud chcete, můžete je použít. Například formátIsFixed="@true"
je neobvyklý, ale podporuje se.
Parameter2.razor
:
@page "/parameter-2"
<PageTitle>Parameter 2</PageTitle>
<h1>Parameter Example 2</h1>
<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() => "From Parent method";
private class PanelData
{
public string Title { get; set; } = "From Parent object";
}
}
Parameter2.razor
:
@page "/parameter-2"
<PageTitle>Parameter 2</PageTitle>
<h1>Parameter Example 2</h1>
<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() => "From Parent method";
private class PanelData
{
public string Title { get; set; } = "From Parent object";
}
}
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";
}
}
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";
}
}
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 jazyka C# k parametru komponenty nepoužívejte předponu atributu HTML parametru @
.
Správně (Title
je řetězcový parametr, Count
je parametr typu číslo):
<ParameterChild Title="@title" Count="ct" />
<ParameterChild Title="@title" Count="@ct" />
Nesprávná odpověď:
<ParameterChild @Title="@title" @Count="ct" />
<ParameterChild @Title="@title" @Count="@ct" />
Na rozdíl od stránek Razor (.cshtml
) nemůže Blazor ve výrazech Razor provádět asynchronní činnost při vykreslování komponent. Důvodem je to, že architektura Blazor je určená k vykreslování interaktivních uživatelských rozhraní. V interaktivním uživatelském rozhraní se na obrazovce vždy musí něco zobrazovat, takže nedává smysl blokovat tok vykreslování. Místo toho se asynchronní činnost provádí během některé z asynchronních událostí životního cyklu. Po každé asynchronní události životního cyklu se komponenta může vykreslit znovu. Následující syntaxe Razor se nepodporuje:
<ParameterChild Title="await ..." />
<ParameterChild Title="@await ..." />
Kód ve výše uvedeném příkladu při sestavování aplikace vygeneruje chybu kompilátoru:
Operátor await je možné použít pouze v rámci asynchronní metody. Zvažte označení této metody pomocí modifikátoru async a změnu jejího návratového typu na Task.
K asynchronnímu získání hodnoty parametru Title
ve výše uvedeném příkladu může komponenta použít událost životního cyklu OnInitializedAsync
, jak ukazuje následující příklad:
<ParameterChild Title="@title" />
@code {
private string? title;
protected override async Task OnInitializedAsync()
{
title = await ...;
}
}
Další informace najdete v tématu Životní cyklus komponent ASP.NET Core Razor.
Použití explicitního výrazu Razor k zřetězení textu s výsledkem výrazu kvůli přiřazení k parametru se nepodporuje. Následující příklad se pokouší zřetězit text Set by
s hodnotou vlastnosti objektu. I když se tato syntaxe podporuje na stránkách Razor (.cshtml
), není možné ji použít k přiřazení parametru Title
podřízeného prvku v komponentě. Následující syntaxe Razor se nepodporuje:
<ParameterChild Title="Set by @(panelData.Title)" />
Kód ve výše uvedeném příkladu při sestavování aplikace vygeneruje chybu kompilátoru:
Atributy komponent nepodporují komplexní obsah (kombinace kódu jazyka C# a HTML).
K přiřazení složené hodnoty použijte metodu, pole nebo vlastnost. Následující příklad provede zřetězení textu Set by
a hodnoty vlastnosti objektu v metodě GetTitle
jazyka C#:
Parameter3.razor
:
@page "/parameter-3"
<PageTitle>Parameter 3</PageTitle>
<h1>Parameter Example 3</h1>
<ParameterChild Title="@GetTitle()" />
@code {
private PanelData panelData = new();
private string GetTitle() => $"Set by {panelData.Title}";
private class PanelData
{
public string Title { get; set; } = "Parent";
}
}
Parameter3.razor
:
@page "/parameter-3"
<PageTitle>Parameter 3</PageTitle>
<h1>Parameter Example 3</h1>
<ParameterChild Title="@GetTitle()" />
@code {
private PanelData panelData = new();
private string GetTitle() => $"Set by {panelData.Title}";
private class PanelData
{
public string Title { get; set; } = "Parent";
}
}
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";
}
}
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";
}
}
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";
}
}
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 najdete v referenčních informacích k syntaxi Razor pro ASP.NET Core.
Upozorňující
Zadání počátečních hodnot parametrů komponent se podporuje, ale nevytvářejte komponenty, které po prvotním vykreslení zapisují do vlastních parametrů. Další informace naleznete v tématu Vyhněte se přepsání parametrů v ASP.NET Core Blazor.
Parametry komponent by se měly deklarovat jako automatické vlastnosti, což znamená, že by neměly obsahovat vlastní logiku v přístupových objektech get
a set
. Příkladem automatické vlastnosti je následující vlastnost StartData
:
[Parameter]
public DateTime StartData { get; set; }
Neumisťujte vlastní logiku do přístupových objektů get
a set
, protože parametry komponent slouží k použití výhradně jako kanál, kterým proudí informace z nadřazené komponenty do podřízené komponenty. Pokud přístupový objekt set
vlastnosti podřízené komponenty obsahuje logiku, která způsobuje vykreslení nadřazené komponenty, vznikne nekonečná smyčka vykreslování.
Transformace přijaté hodnoty parametru:
- Ponechte vlastnost parametru jako automatickou vlastnost, aby představovala zadaná nezpracovaná data.
- Vytvořte jinou vlastnost nebo metodu, která bude poskytovat transformovaná data na základě vlastnosti parametru.
Přepište metodu OnParametersSetAsync
tak, aby při každém přijetí nových dat transformovala přijatý parametr.
Zápis počátečních hodnot parametrů komponent se podporuje, protože počáteční přiřazené hodnoty neovlivňují automatické vykreslování komponent architektury Blazor. Následující přiřazení aktuálního místního data a času (DateTime) pomocí vlastnosti DateTime.Now k parametru StartData
je v komponentě platná syntaxe:
[Parameter]
public DateTime StartData { get; set; } = DateTime.Now;
Po počátečním přiřazení vlastnosti DateTime.Nownepřiřazujte hodnotu k parametru StartData
v kódu vývojáře. Další informace naleznete v tématu Vyhněte se přepsání parametrů v ASP.NET Core Blazor.
K zadání požadovaného parametru komponenty použijte atribut [EditorRequired]
. Pokud se nezadá hodnota požadovaného parametru, v editoru nebo nástrojích pro sestavování se může uživateli zobrazit upozornění. Tento atribut je platný pouze u vlastností označených také atributem [Parameter]
. Atribut EditorRequiredAttribute se vynucuje v době návrhu a při sestavování aplikace. Tento atribut se nevynucuje za běhu a nezaručuje, že parametr nebude mít hodnotu null
.
[Parameter]
[EditorRequired]
public string? Title { get; set; }
Podporují se také jednořádkové seznamy atributů:
[Parameter, EditorRequired]
public string? Title { get; set; }
Nepoužívejte required
modifikátor aniinit
přístup k vlastnostem parametru komponenty. Komponenty se obvykle vytvářejí a přiřazují hodnoty parametrů pomocí reflexe, která obchází záruky, které init
jsou required
navrženy k vytvoření. Místo toho použijte [EditorRequired]
atribut k určení požadovaného parametru komponenty.
Nepoužívejte přístup k vlastnostem parametruinit
komponenty, protože nastavení hodnot parametrů komponenty s ParameterView.SetParameterProperties použitím reflexe, které obchází omezení init-only setter. Pomocí atributu [EditorRequired]
zadejte požadovaný parametr komponenty.
Nepoužívejte přístup k vlastnostem parametruinit
komponenty, protože nastavení hodnot parametrů komponenty s ParameterView.SetParameterProperties použitím reflexe, které obchází omezení init-only setter.
Jako parametry komponent a typy Tuples
se podporují řazené kolekce členů ( – RenderFragment
). Následující příklad parametru komponenty předá v řazené kolekci členů Tuple
tři hodnoty:
RenderTupleChild.razor
:
<div class="card w-50" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Tuple Card</div>
<div class="card-body">
<ul>
<li>Integer: @Data?.Item1</li>
<li>String: @Data?.Item2</li>
<li>Boolean: @Data?.Item3</li>
</ul>
</div>
</div>
@code {
[Parameter]
public (int, string, bool)? Data { get; set; }
}
RenderTupleParent.razor
:
@page "/render-tuple-parent"
<PageTitle>Render Tuple Parent</PageTitle>
<h1>Render Tuple Parent Example</h1>
<RenderTupleChild Data="data" />
@code {
private (int, string, bool) data = new(999, "I aim to misbehave.", true);
}
Pojmenované řazené kolekce členů se podporují, jak je vidět v následujícím příkladu:
NamedTupleChild.razor
:
<div class="card w-50" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Tuple Card</div>
<div class="card-body">
<ul>
<li>Integer: @Data?.TheInteger</li>
<li>String: @Data?.TheString</li>
<li>Boolean: @Data?.TheBoolean</li>
</ul>
</div>
</div>
@code {
[Parameter]
public (int TheInteger, string TheString, bool TheBoolean)? Data { get; set; }
}
NamedTuples.razor
:
@page "/named-tuples"
<PageTitle>Named Tuples</PageTitle>
<h1>Named Tuples Example</h1>
<NamedTupleChild Data="data" />
@code {
private (int TheInteger, string TheString, bool TheBoolean) data =
new(999, "I aim to misbehave.", true);
}
Citace ©2005 Universal Pictures: Serenity (Nathan Fillion)
Jako parametry komponent a typy Tuples
se podporují řazené kolekce členů ( – RenderFragment
). Následující příklad parametru komponenty předá v řazené kolekci členů Tuple
tři hodnoty:
RenderTupleChild.razor
:
<div class="card w-50" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Tuple Card</div>
<div class="card-body">
<ul>
<li>Integer: @Data?.Item1</li>
<li>String: @Data?.Item2</li>
<li>Boolean: @Data?.Item3</li>
</ul>
</div>
</div>
@code {
[Parameter]
public (int, string, bool)? Data { get; set; }
}
RenderTupleParent.razor
:
@page "/render-tuple-parent"
<PageTitle>Render Tuple Parent</PageTitle>
<h1>Render Tuple Parent Example</h1>
<RenderTupleChild Data="data" />
@code {
private (int, string, bool) data = new(999, "I aim to misbehave.", true);
}
Pojmenované řazené kolekce členů se podporují, jak je vidět v následujícím příkladu:
NamedTupleChild.razor
:
<div class="card w-50" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Tuple Card</div>
<div class="card-body">
<ul>
<li>Integer: @Data?.TheInteger</li>
<li>String: @Data?.TheString</li>
<li>Boolean: @Data?.TheBoolean</li>
</ul>
</div>
</div>
@code {
[Parameter]
public (int TheInteger, string TheString, bool TheBoolean)? Data { get; set; }
}
NamedTuples.razor
:
@page "/named-tuples"
<PageTitle>Named Tuples</PageTitle>
<h1>Named Tuples Example</h1>
<NamedTupleChild Data="data" />
@code {
private (int TheInteger, string TheString, bool TheBoolean) data =
new(999, "I aim to misbehave.", true);
}
Citace ©2005 Universal Pictures: Serenity (Nathan Fillion)
Jako parametry komponent a typy Tuples
se podporují řazené kolekce členů ( – RenderFragment
). Následující příklad parametru komponenty předá v řazené kolekci členů Tuple
tři hodnoty:
RenderTupleChild.razor
:
<div class="card w-50" style="margin-bottom:15px">
<div class="card-header font-weight-bold"><code>Tuple</code> Card</div>
<div class="card-body">
<ul>
<li>Integer: @Data?.Item1</li>
<li>String: @Data?.Item2</li>
<li>Boolean: @Data?.Item3</li>
</ul>
</div>
</div>
@code {
[Parameter]
public (int, string, bool)? Data { get; set; }
}
RenderTupleParent.razor
:
@page "/render-tuple-parent"
<h1>Render Tuple Parent</h1>
<RenderTupleChild Data="data" />
@code {
private (int, string, bool) data = new(999, "I aim to misbehave.", true);
}
Pojmenované řazené kolekce členů se podporují, jak je vidět v následujícím příkladu:
RenderNamedTupleChild.razor
:
<div class="card w-50" style="margin-bottom:15px">
<div class="card-header font-weight-bold"><code>Tuple</code> Card</div>
<div class="card-body">
<ul>
<li>Integer: @Data?.TheInteger</li>
<li>String: @Data?.TheString</li>
<li>Boolean: @Data?.TheBoolean</li>
</ul>
</div>
</div>
@code {
[Parameter]
public (int TheInteger, string TheString, bool TheBoolean)? Data { get; set; }
}
RenderNamedTupleParent.razor
:
@page "/render-named-tuple-parent"
<h1>Render Named Tuple Parent</h1>
<RenderNamedTupleChild Data="data" />
@code {
private (int TheInteger, string TheString, bool TheBoolean) data =
new(999, "I aim to misbehave.", true);
}
Citace ©2005 Universal Pictures: Serenity (Nathan Fillion)
Parametry trasy
Komponenty umožňují v šabloně trasy u direktivy @page
zadat parametry trasy.
Směrovač Blazor na základě parametrů trasy vyplní odpovídající parametry komponenty.
RouteParameter1.razor
:
@page "/route-parameter-1/{text}"
<PageTitle>Route Parameter 1</PageTitle>
<h1>Route Parameter Example 1</h1>
<p>Blazor is @Text!</p>
@code {
[Parameter]
public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"
<PageTitle>Route Parameter 1</PageTitle>
<h1>Route Parameter Example 1</h1>
<p>Blazor is @Text!</p>
@code {
[Parameter]
public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string Text { get; set; }
}
@page "/route-parameter-1/{text}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string Text { get; set; }
}
Další informace najdete v Blazor jádra. Volitelné parametry trasy se také podporují a pokrývají ve stejné části. Informace o parametrech trasy catch-all ({*pageRoute}
), které zachycují cesty přes hranice více složek, najdete v části Parametry trasy catch-all ASP.NET Core Blazor směrování a navigace.
Další informace najdete v Blazor jádra. Volitelné parametry trasy nejsou podporované, takže jsou vyžadovány dvě @page
direktivy (další informace najdete v části Parametry trasy). Informace o parametrech trasy catch-all ({*pageRoute}
), které zachycují cesty přes hranice více složek, najdete v části Parametry trasy catch-all ASP.NET Core Blazor směrování a navigace.
Upozorňující
Díky kompresi, která je ve výchozím nastavení povolená, se vyhněte vytváření zabezpečených (ověřených/autorizovaných) interaktivních komponent na straně serveru, které vykreslují data z nedůvěryhodných zdrojů. Mezi nedůvěryhodné zdroje patří parametry směrování, řetězce dotazů, data z JS interoperability a jakýkoli jiný zdroj dat, který může uživatel třetí strany řídit (databáze, externí služby). Další informace najdete v pokynech SignalRa Blazor na straně serveru ASP.NET Core.
Fragmenty vykreslování podřízeného obsahu
Komponenty můžou nastavit obsah jiné komponenty. Přiřazující komponenta zadává obsah mezi počáteční a koncovou značku podřízené komponenty.
V následujícím příkladu komponenta RenderFragmentChild
obsahuje parametr komponenty ChildContent
, který představuje segment uživatelského rozhraní, který se má vykreslit jako RenderFragment. Ve výsledném výstupu HTML se obsah vykreslí na pozici, kde se v kódu ChildContent
komponenty nachází Razor.
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; }
}
<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; }
}
<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; }
}
<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; }
}
<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; }
}
<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é
Podle konvence musí mít vlastnost přijímající obsah RenderFragment název ChildContent
.
nepodporuje RenderFragment.
Následující komponenta poskytuje obsah pro vykreslení RenderFragmentChild
umístěním obsahu do úvodní a koncové značky podřízené komponenty.
RenderFragments.razor
:
@page "/render-fragments"
<PageTitle>Render Fragments</PageTitle>
<h1>Render Fragments Example</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
RenderFragments.razor
:
@page "/render-fragments"
<PageTitle>Render Fragments</PageTitle>
<h1>Render Fragments Example</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
RenderFragmentParent.razor
:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
RenderFragmentParent.razor
:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
RenderFragmentParent.razor
:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
RenderFragmentParent.razor
:
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
Fragmenty vykreslování se používají k vykreslování podřízeného obsahu napříč aplikacemi Blazor a jejich popis i s příklady najdete v následujících článcích a částech:
- Rozložení Blazor
- Předávání dat napříč hierarchií komponent
- Šablonované komponenty
- Globální zpracování výjimek
Poznámka:
Razor v architektuře při nastavování svého obsahu dodržují stejnou konvenci pro parametry komponent ChildContent
. Informace o komponentách, které nastavují podřízený obsah vyhledáním názvu vlastnosti parametru komponenty ChildContent
, najdete v dokumentaci k rozhraní API (k filtrování rozhraní API se použije hledaný výraz ChildContent).
Fragmenty vykreslování pro opakovaně použitelnou logiku vykreslování
Podřízené komponenty můžete využít čistě jako způsob opakovaného používání logiky vykreslování. V libovolném bloku @code
komponenty můžete definovat RenderFragment a vykreslit tento fragment na jakémkoli místě a kolikrát je potřeba:
@RenderWelcomeInfo
<p>Render the welcome info a second time:</p>
@RenderWelcomeInfo
@code {
private RenderFragment RenderWelcomeInfo = @<p>Welcome to your new app!</p>;
}
Další informace najdete v tématu Opakované používání logiky vykreslování.
Proměnné smyčky s parametry komponent a podřízeným obsahem
Vykreslování komponent uvnitř for
smyčky vyžaduje místní indexovou proměnnou, pokud je proměnná inkrementační smyčky používána parametry komponenty nebo RenderFragment podřízeným obsahem.
Zvažte následující RenderFragmentChild2
komponentu, která má parametr komponenty (Id
) i fragment vykreslení pro zobrazení podřízeného obsahu (ChildContent
).
RenderFragmentChild2.razor
:
<div class="card w-25" style="margin-bottom:15px">
<div class="card-header font-weight-bold">Child content (@Id)</div>
<div class="card-body">@ChildContent</div>
</div>
@code {
[Parameter]
public string? Id { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
}
Při vykreslování RenderFragmentChild2
komponenty v nadřazené komponentě použijte místní indexovou proměnnou (ct
v následujícím příkladu) místo proměnné smyčky (c
) při přiřazování hodnoty parametru komponenty a poskytnutí obsahu podřízené komponenty:
@for (int c = 1; c < 4; c++)
{
var ct = c;
<RenderFragmentChild2 Id="@($"Child{ct}")">
Count: @ct
</RenderFragmentChild2>
}
Alternativně můžete místo smyčky použít foreach
smyčku Enumerable.Rangefor
:
@foreach (var c in Enumerable.Range(1, 3))
{
<RenderFragmentChild2 Id="@($"Child{c}")">
Count: @c
</RenderFragmentChild2>
}
Zachytávání odkazů na komponenty
Odkazy na komponenty umožňují odkazovat na instance komponent při vydávání příkazů. Zachycení odkazu na komponentu:
- Přidejte do podřízené komponenty atribut
@ref
. - Definujte pole stejného typu jako podřízená komponenta.
Při vykreslení komponenty se toto pole vyplní instancí komponenty. Pak můžete nad touto instancí volat metody .NET.
Podívejte se například na následující komponentu ReferenceChild
, která zaprotokoluje zprávu při zavolání její metody ChildMethod
.
ReferenceChild.razor
:
@inject ILogger<ReferenceChild> Logger
@if (value > 0)
{
<p>
<code>value</code>: @value
</p>
}
@code {
private int value;
public void ChildMethod(int value)
{
Logger.LogInformation("Received {Value} in ChildMethod", value);
this.value = value;
StateHasChanged();
}
}
@inject ILogger<ReferenceChild> Logger
@if (value > 0)
{
<p>
<code>value</code>: @value
</p>
}
@code {
private int value;
public void ChildMethod(int value)
{
Logger.LogInformation("Received {Value} in ChildMethod", value);
this.value = value;
StateHasChanged();
}
}
@using Microsoft.Extensions.Logging
@inject ILogger<ReferenceChild> Logger
@code {
public void ChildMethod(int value)
{
Logger.LogInformation("Received {Value} in ChildMethod", value);
}
}
@using Microsoft.Extensions.Logging
@inject ILogger<ReferenceChild> Logger
@code {
public void ChildMethod(int value)
{
Logger.LogInformation("Received {Value} in ChildMethod", value);
}
}
@using Microsoft.Extensions.Logging
@inject ILogger<ReferenceChild> Logger
@code {
public void ChildMethod(int value)
{
Logger.LogInformation("Received {Value} in ChildMethod", value);
}
}
@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 jeho výstup obsahuje element komponenty ReferenceChild
. Dokud se komponenta nevykreslí, není na co odkazovat. Nepokoušejte se volat metodu odkazované komponenty obslužné rutině události přímo (například @onclick="childComponent!.ChildMethod(5)"
), protože odkazová proměnná nemusí být přiřazena v době přiřazení události kliknutí.
Pokud chcete manipulovat s odkazy na komponenty po dokončení jejich vykreslování, použijte metodu OnAfterRender
nebo OnAfterRenderAsync
.
Následující příklad používá předchozí komponentu ReferenceChild
.
ReferenceParent.razor
:
@page "/reference-parent"
<div>
<button @onclick="@(() => childComponent1!.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> (first instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent1" />
</div>
<div>
<button @onclick="CallChildMethod">
Call <code>ReferenceChild.ChildMethod</code> (second instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent2" />
</div>
@code {
private ReferenceChild? childComponent1;
private ReferenceChild? childComponent2;
private void CallChildMethod() => childComponent2!.ChildMethod(5);
}
@page "/reference-parent"
<div>
<button @onclick="@(() => childComponent1!.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> (first instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent1" />
</div>
<div>
<button @onclick="CallChildMethod">
Call <code>ReferenceChild.ChildMethod</code> (second instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent2" />
</div>
@code {
private ReferenceChild? childComponent1;
private ReferenceChild? childComponent2;
private void CallChildMethod() => childComponent2!.ChildMethod(5);
}
@page "/reference-parent"
<div>
<button @onclick="@(() => childComponent1!.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> (first instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent1" />
</div>
<div>
<button @onclick="CallChildMethod">
Call <code>ReferenceChild.ChildMethod</code> (second instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent2" />
</div>
@code {
private ReferenceChild? childComponent1;
private ReferenceChild? childComponent2;
private void CallChildMethod()
{
childComponent2!.ChildMethod(5);
}
}
@page "/reference-parent"
<div>
<button @onclick="@(() => childComponent1!.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> (first instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent1" />
</div>
<div>
<button @onclick="CallChildMethod">
Call <code>ReferenceChild.ChildMethod</code> (second instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent2" />
</div>
@code {
private ReferenceChild? childComponent1;
private ReferenceChild? childComponent2;
private void CallChildMethod()
{
childComponent2!.ChildMethod(5);
}
}
@page "/reference-parent"
<div>
<button @onclick="@(() => childComponent1!.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> (first instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent1" />
</div>
<div>
<button @onclick="CallChildMethod">
Call <code>ReferenceChild.ChildMethod</code> (second instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent2" />
</div>
@code {
private ReferenceChild childComponent1;
private ReferenceChild childComponent2;
private void CallChildMethod()
{
childComponent2!.ChildMethod(5);
}
}
@page "/reference-parent"
<div>
<button @onclick="@(() => childComponent1!.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> (first instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent1" />
</div>
<div>
<button @onclick="CallChildMethod">
Call <code>ReferenceChild.ChildMethod</code> (second instance)
with an argument of 5
</button>
<ReferenceChild @ref="childComponent2" />
</div>
@code {
private ReferenceChild childComponent1;
private ReferenceChild childComponent2;
private void CallChildMethod()
{
childComponent2!.ChildMethod(5);
}
}
Při zachytávání odkazů na komponenty se používá podobná syntaxe jako při zachytávání odkazů na elementy, protože zachytávání odkazů na komponenty není funkce interoperability JavaScriptu. Odkazy na komponenty se nepředávají do kódu JavaScriptu. Odkazy na komponenty se používají pouze v kódu .NET.
Důležité
Nepoužívejte odkazy na komponenty k úpravě stavu podřízených komponent. Místo toho k předávání dat do podřízených komponent používejte běžné deklarativní parametry komponent. Použitím parametrů komponent se zajistí automatické opětovné vykreslování podřízených komponent ve správnou dobu. Další informace najdete v části Parametry komponent a v článku Datové vazby ASP.NET Core Blazor.
Použití atributu
Atributy je možné použít na komponenty pomocí direktivy @attribute
. Následující příklad použije na třídu komponenty atribut [Authorize]
:
@page "/"
@attribute [Authorize]
Atributy podmíněného elementu HTML a vlastnosti DOM
Blazor přijímá následující obecné chování:
- U atributů Blazor HTML nastaví nebo odebere atribut podmíněně na základě hodnoty .NET. Pokud je
false
hodnota .NET nebonull
, atribut není nastaven nebo je odebrán, pokud byl dříve nastaven. - U vlastností MODELU DOM, například
checked
nebovalue
, Blazor nastaví vlastnost MODELU DOM na základě hodnoty .NET. Pokud jefalse
hodnota .NET nebonull
, vlastnost DOM je resetována na výchozí hodnotu.
Které Razor atributy syntaxe odpovídají atributům HTML a které odpovídají vlastnostem MODELU DOM, zůstávají nezdokumentované, protože se jedná o podrobnosti implementace architektury, které se mohou bez předchozího upozornění změnit.
Upozorňující
Některé atributy HTML, například aria-pressed
, musí mít řetězcovou hodnotu "true" nebo "false". Vzhledem k tomu, že vyžadují řetězcovou hodnotu, nikoli logickou hodnotu, musíte pro jejich hodnotu použít .NET string
, nikoli hodnotu bool
. Toto je požadavek nastavený rozhraními API DOM prohlížeče.
Nezpracovaný kód HTML
Řetězce se obvykle vykreslují s využitím textových uzlů DOM, což znamená, že se veškerý kód HTML, který obsahují, ignoruje a považuje za prostý text. Pokud chcete vykreslit nezpracovaný kód HTML, zabalte obsah HTML do hodnoty MarkupString. Tato hodnota se parsuje jako HTML nebo SVG a vloží se do modelu DOM.
Upozorňující
Vykreslování nezpracovaného kódu HTML z nedůvěryhodných zdrojů představuje bezpečnostní riziko a je potřeba se tomu vždy vyhnout.
Následující příklad ukazuje použití typu MarkupString k přidání bloku statického obsahu HTML do vykresleného výstupu komponenty.
MarkupStrings.razor
:
@page "/markup-strings"
<PageTitle>Markup Strings</PageTitle>
<h1>Markup Strings Example</h1>
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
MarkupStrings.razor
:
@page "/markup-strings"
<PageTitle>Markup Strings</PageTitle>
<h1>Markup Strings Example</h1>
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
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>";
}
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>";
}
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>";
}
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>";
}
Šablony Razor
Fragmenty vykreslování je možné definovat pomocí syntaxe šablony Razor pro definování fragmentu kódu uživatelského rozhraní. Šablony Razor používají následující formát:
@<{HTML tag}>...</{HTML tag}>
Následující příklad ukazuje, jak zadat hodnoty RenderFragment a RenderFragment<TValue> a vykreslit šablony přímo v komponentě. Fragmenty vykreslování je možné také předávat jako argumenty do komponent bez vizuálního vzhledu.
RazorTemplate.razor
:
@page "/razor-template"
<PageTitle>Razor Template</PageTitle>
<h1>Razor Template Example</h1>
@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; }
}
}
@page "/razor-template"
<PageTitle>Razor Template</PageTitle>
<h1>Razor Template Example</h1>
@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; }
}
}
@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; }
}
}
@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; }
}
}
@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; }
}
}
@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 výše uvedeného kódu:
<p>The time is 4/19/2021 8:54:46 AM.</p>
<p>Pet: Nutty Rex</p>
Statické prostředky
Blazor dodržuje konvenci aplikací ASP.NET Core pro statické prostředky. Statické prostředky se nacházejí ve složce web root
(wwwroot
) projektu nebo v podsložkách složky wwwroot
.
K odkazování na kořenový adresář webu se statickými prostředky použijte základní relativní cestu (/
). V následujícím příkladu se soubor logo.png
fyzicky nachází ve složce {PROJECT ROOT}/wwwroot/images
.
{PROJECT ROOT}
je kořenový adresář projektu aplikace.
<img alt="Company logo" src="/images/logo.png" />
Komponenty nepodporují notaci znaku tildy s lomítkem (~/
).
Informace o nastavení základní cesty aplikace najdete v tématu Hostování a nasazování aplikací ASP.NET Core Blazor.
Pomocné rutiny značek se v komponentách nepodporují
V komponentách se nepodporují pomocné rutiny značek (Tag Helpers
). Pokud chcete v architektuře Blazor dosáhnout podobných funkcí, jaké nabízejí pomocné rutiny značek, vytvořte komponentu se stejnou funkcí jako pomocná rutina značky a použijte místo ní tuto komponentu.
Obrázky ve formátu SVG (Scalable Vector Graphics)
Vzhledem k tomu, že Blazor vykresluje kód HTML, značka .svg
podporuje všechny obrázky podporované prohlížečem, včetně <img>
.
<img alt="Example image" src="image.svg" />
Podobně se obrázky ve formátu SVG podporují i v pravidlech CSS v souborech šablon stylů (.css
):
.element-class {
background-image: url("image.svg");
}
Blazor podporuje element <foreignObject>
umožňující zobrazit v rámci obrázku ve formátu SVG libovolný kód HTML. Kód může představovat libovolný kód HTML, delegáta RenderFragment nebo komponentu Razor.
Následující příklad ukazuje:
- Zobrazení řetězce typu
string
(@message
) - Dvousměrnou vazbu s elementem
<input>
a polemvalue
- Komponentu
Robot
<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í při vykreslování prázdných znaků
Pokud se direktiva @preservewhitespace
nepoužije s hodnotou true
, nadbytečné prázdné znaky se odeberou, pokud:
- Na začátku nebo na konci elementu
- Na začátku nebo na konci parametru RenderFragment/RenderFragment<TValue> (například podřízený obsah předaný do jiné komponenty)
- Před nebo za blokem kódu jazyka C#, například
@if
nebo@foreach
Při použití pravidla CSS, jako je white-space: pre
, může mít odebrání prázdných znaků vliv na vykreslený výstup. Pokud chcete tuto optimalizaci výkonu zakázat a zachovat prázdné znaky, proveďte jednu z následujících akcí:
- Pokud chcete tuto předvolbu použít na konkrétní komponentu, přidejte direktivu
@preservewhitespace true
na začátek souboru Razor (.razor
). - Pokud chcete tuto předvolbu použít na podadresář nebo celý projekt, přidejte direktivu
@preservewhitespace true
do souboru_Imports.razor
.
Ve většině případů se nevyžaduje žádná akce, protože aplikace obvykle dál fungují normálně (ale rychleji). Pokud odstraňování prázdných znaků způsobuje problém s vykreslováním u konkrétní komponenty, použijte k zákazu této optimalizace v dané komponentě direktivu @preservewhitespace true
.
Prázdné znaky ve zdrojovém kódu komponent se zachovávají. Text složený pouze z prázdných znaků se vykreslí v modelu DOM prohlížeče, i když nemá žádný vizuální efekt.
Podívejte se například na kód následující komponenty:
<ul>
@foreach (var item in Items)
{
<li>
@item.Text
</li>
}
</ul>
Výše uvedený příklad vykreslí následující nepotřebné prázdné znaky:
- Mimo blok kódu
@foreach
- Okolo elementu
<li>
- Okolo výstupu
@item.Text
Seznam o 100 položkách obsahuje více než 400 oblastí prázdných znaků. Žádný z nadbytečných prázdných znaků nemá vizuální dopad na vykreslený výstup.
Při vykreslování statického obsahu HTML pro komponenty se nezachovávají prázdné znaky uvnitř značek. Projděte si například vykreslený výstup následující značky <img>
v souboru Razor komponenty (.razor
):
<img alt="Example image" src="img.png" />
Prázdné znaky z výše uvedeného kódu se nezachovají:
<img alt="Example image" src="img.png" />
Kořenová komponenta
Kořenová komponenta (kořenová Razor komponenta) je první komponenta načtená z jakékoli hierarchie komponent, kterou aplikace vytvořila.
V aplikaci vytvořené ze Blazor Web App šablony App
projektu je komponenta (App.razor
) určena jako výchozí kořenová komponenta parametrem typu deklarovaným pro volání MapRazorComponents<TRootComponent>
v souboru na straně Program
serveru. Následující příklad ukazuje použití App
komponenty jako kořenové komponenty, což je výchozí hodnota pro aplikaci vytvořenou Blazor ze šablony projektu:
app.MapRazorComponents<App>();
Poznámka:
Interaktivní vytvoření kořenové komponenty, například App
komponenty, není podporováno.
V aplikaci vytvořené ze Blazor Server šablony App
projektu je komponenta (App.razor
) určena jako výchozí kořenová komponenta pomocí Pages/_Host.cshtml
pomocné rutiny značky komponent:
<component type="typeof(App)" render-mode="ServerPrerendered" />
V aplikaci vytvořené ze Blazor WebAssembly šablony App
projektu je komponenta (App.razor
) určena jako výchozí kořenová komponenta Program
v souboru:
builder.RootComponents.Add<App>("#app");
V předchozím kódu selektor CSS označuje, #app
že součást je určena pro App
<div>
in s hodnotou wwwroot/index.html
id
:app
<div id="app">...</app>
Aplikace MVC a Razor Pages můžou také použít pomocnou rutinu značky komponenty k registraci staticky vykreslených Blazor WebAssembly kořenových komponent:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
Staticky vykreslené komponenty je možné do aplikace přidat pouze. Potom je nejde odebrat ani aktualizovat.
Další informace naleznete v následujících zdrojích:
- Pomocná rutina značek komponent v ASP.NET Core
- Integrace základních komponent ASP.NET Razor s MVC nebo Razor stránkami
IHttpContextAccessor
/HttpContext
Obecně je třeba se vyhnout IHttpContextAccessor při interaktivním vykreslování, protože nemusí být vždy dostupný platný HttpContext.
IHttpContextAccessor lze použít pro součásti, které jsou staticky vykresleny na serveru. Pokud je to ale možné, doporučujeme se tomu vyhnout.
HttpContext lze použít jako kaskádový parametr pouze ve staticky vykreslených kořenových komponentách pro obecné úkoly, například pro kontrolu a úpravu hlaviček nebo jiných vlastností v komponentě App
(Components/App.razor
). Hodnota je vždy null
pro interaktivní vykreslování.
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
Ve scénářích, kdy je HttpContext vyžadováno v interaktivních komponentách, doporučujeme předávat data prostřednictvím perzistentního stavu komponenty ze serveru. Pro více informací viz serverová část ASP.NET Core a Blazor Web App další bezpečnostní scénáře.
Nepoužívejte IHttpContextAccessor/HttpContext přímo ani nepřímo v Razor komponentách Blazor aplikací na straně serveru. Blazor aplikace běží mimo kontext kanálu ASP.NET Core. Není zaručeno, že HttpContext bude dostupné v rámci IHttpContextAccessor, a není zaručeno, že HttpContext bude obsahovat kontext, který spustil aplikaci Blazor.
Doporučený postup pro předání stavu požadavku do aplikace Blazor je prostřednictvím parametrů kořenové komponenty během počátečního vykreslování aplikace. Případně může aplikace zkopírovat data do vymezené služby v události životního cyklu inicializace kořenové komponenty pro použití v celé aplikaci. Další informace viz k serverové části ASP.NET Core a Blazor Web App dalším scénářům zabezpečení.
Důležitým aspektem zabezpečení Blazor na straně serveru je, že uživatel připojený k danému okruhu může být v určitém okamžiku po navázání okruhu Blazor aktualizován, ale IHttpContextAccessorseneaktualizuje. Další informace o řešení této situace s vlastními službami najdete v části serveru ASP.NET Core a v dalších scénářích zabezpečeníBlazor Web App.