Sdílet prostřednictvím


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:

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 že ProductDetail komponenta má název ProductDetail.razor souboru a nachází se ve Pages složce Components 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 je BlazorSample.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ů BlazorSampleBlazorSample.Components.Pages pro komponentu Home . {PROJECT NAMESPACE} je obor názvů projektu. Komponenty dodržují pravidla vazby názvů jazyka C#. Pro komponentu Home 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ů

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 komponentu NavMenu ve složce Components/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 komponenty ProductDetail má název ProductDetail.razor a nachází se ve složce Pages 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 je BlazorSample.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ů BlazorSampleBlazorSample.Pages pro komponentu Index . {PROJECT NAMESPACE} je obor názvů projektu. Komponenty dodržují pravidla vazby názvů jazyka C#. Pro komponentu Index 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ů

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 komponentu NavMenu ve složce Shared 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-worldtrasy 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 NavLinkNavMenu . 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 CSS font-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 a Body z komponenty ParameterParent, 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:

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", kde ct 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říklad this) a null, ale pokud chcete, můžete je použít. Například formát IsFixed="@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 aniinitpří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 parametruinitkomponenty, 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 parametruinitkomponenty, 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:

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 nebo null, atribut není nastaven nebo je odebrán, pokud byl dříve nastaven.
  • U vlastností MODELU DOM, například checked nebo value, Blazor nastaví vlastnost MODELU DOM na základě hodnoty .NET. Pokud je false hodnota .NET nebo null, 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 polem value
  • 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.htmlid: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:

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.