Delen via


ASP.NET Core Razor-onderdelen

Notitie

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikelvoor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie de .NET- en .NET Core-ondersteuningsbeleidvoor meer informatie. Zie de .NET 9-versie van dit artikelvoor de huidige release.

Belangrijk

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikelvoor de huidige release.

In dit artikel wordt uitgelegd hoe u Razor onderdelen maakt en gebruikt in Blazor-apps, waaronder richtlijnen voor Razor syntaxis, naamgeving van onderdelen, naamruimten en onderdeelparameters.

Razor onderdelen

Blazor-apps zijn gebouwd met Razor onderdelen, informeel bekend als Blazor onderdelen of alleen onderdelen. Een onderdeel is een zelfstandig gedeelte van de gebruikersinterface (UI) met verwerkingslogica om dynamisch gedrag mogelijk te maken. Onderdelen kunnen worden genest, hergebruikt, gedeeld tussen projecten en worden gebruikt in MVC- en Razor Pages-apps.

Onderdelen worden weergegeven als een in-memory representatie van de Document Object Model (DOM) van de browser, genaamd een weergavestructuur, die wordt gebruikt om de gebruikersinterface op een flexibele en efficiënte manier bij te werken.

Hoewel "Razor onderdelen" een naamgeving deelt met andere ASP.NET Core-technologieën voor inhoudsweergave, moeten Razor onderdelen worden onderscheiden van de volgende verschillende functies in ASP.NET Core:

Belangrijk

Wanneer u een Blazor Web Appgebruikt, moeten de meeste van de Blazor voorbeeldonderdelen van documentatie interactiviteit functioneren en de concepten laten zien die in de artikelen worden behandeld. Wanneer u een voorbeeldonderdeel test dat wordt geleverd door een artikel, moet u ervoor zorgen dat de app gebruikmaakt van wereldwijde interactiviteit of dat het onderdeel een interactieve rendermodus gebruikt. Meer informatie over dit onderwerp vindt u in ASP.NET Core Blazor rendermodi. Dit is het volgende artikel in de inhoudsopgave na dit artikel.

Onderdeelklassen

Onderdelen worden geïmplementeerd met behulp van een combinatie van C# en HTML-opmaak in Razor onderdeelbestanden met de bestandsextensie .razor.

ComponentBase is de basisklasse voor onderdelen die worden beschreven door Razor onderdeelbestanden. ComponentBase implementeert de laagste abstractie van onderdelen, de IComponent interface. ComponentBase definieert onderdeeleigenschappen en -methoden voor basisfunctionaliteit, bijvoorbeeld om een set ingebouwde levenscyclusgebeurtenissen voor onderdelen te verwerken.

ComponentBase in dotnet/aspnetcore referentiebron: de referentiebron bevat aanvullende opmerkingen over de ingebouwde levenscyclusgebeurtenissen. Houd er echter rekening mee dat de interne implementaties van onderdeelfuncties op elk moment zonder kennisgeving kunnen worden gewijzigd.

Notitie

Documentatiekoppelingen naar .NET-referentiebron laden meestal de standaardbranch van de opslagplaats, die de huidige ontwikkeling vertegenwoordigt voor de volgende release van .NET. Als u een tag voor een specifieke release wilt selecteren, gebruikt u de Switch-vertakkingen of tags vervolgkeuzelijst. Zie Een versietag selecteren van ASP.NET Core-broncode (dotnet/AspNetCore.Docs #26205)voor meer informatie.

Ontwikkelaars maken doorgaans Razor onderdelen van Razor onderdeelbestanden (.razor) of baseren hun onderdelen op ComponentBase, maar onderdelen kunnen ook worden gebouwd door IComponentte implementeren. Door ontwikkelaars gebouwde onderdelen die IComponent implementeren, kunnen controle op rendering op laag niveau overnemen ten koste van het handmatig activeren van rendering met gebeurtenissen en levenscyclusmethoden die de ontwikkelaar moet maken en onderhouden.

Aanvullende conventies die worden aangenomen door Blazor voorbeeldcode en voorbeeld-apps van documentatie, vindt u in ASP.NET Core Blazor fundamentals.

Razor syntaxis

Onderdelen gebruiken Razor syntaxis. Twee Razor kenmerken worden uitgebreid gebruikt door onderdelen, richtlijnen en richtlijnkenmerken. Dit zijn gereserveerde trefwoorden voorafgegaan door @ die worden weergegeven in Razor markeringen:

  • richtlijnen: Wijzig de manier waarop component-markup wordt gecompileerd of werkt. De @page-instructie geeft bijvoorbeeld een routeerbaar onderdeel op met een routesjabloon die rechtstreeks kan worden bereikt door de aanvraag van een gebruiker in de browser op een specifieke URL.

    Volgens de conventie worden de richtlijnen van een onderdeel boven aan een onderdeeldefinitie (.razor bestand) in een consistente volgorde geplaatst. Voor herhaalde instructies worden richtlijnen alfabetisch op naamruimte of type geplaatst, met uitzondering van @using richtlijnen, die een speciale volgorde op het tweede niveau hebben.

    De volgende volgorde wordt gebruikt door Blazor voorbeeld-apps en documentatie. Onderdelen die worden geleverd door een Blazor projectsjabloon kunnen verschillen van de volgende volgorde en een andere indeling gebruiken. Blazor framework Identity onderdelen bevatten bijvoorbeeld lege regels tussen blokken van @using richtlijnen en blokken van @inject richtlijnen. U kunt een aangepast bestelschema en een aangepaste indeling gebruiken in uw eigen apps.

    Documentatie en voorbeeld-app Razor instructievolgorde:

    • @page
    • @rendermode (.NET 8 of hoger)
    • @using
      • System naamruimten (alfabetische volgorde)
      • Microsoft naamruimten (alfabetische volgorde)
      • API-naamruimten van derden (alfabetische volgorde)
      • App-naamruimten (alfabetische volgorde)
    • Overige richtlijnen (alfabetische volgorde)

    Er worden geen lege regels weergegeven in de richtlijnen. Er wordt een lege regel weergegeven tussen de instructies en de eerste regel van Razor markeringen.

    Voorbeeld:

    @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>
    
    ...
    
  • Richtlijnkenmerken: De manier wijzigen waarop een onderdeelelement wordt gecompileerd of functies.

    Voorbeeld:

    <input @bind="episodeId" />
    

    U kunt de kenmerkwaarden van de instructie vooraf laten gaan met het at-symbool (@) voor niet-expliciete Razor expressies (@bind="@episodeId"), maar we raden dit niet aan en de documenten gebruiken de benadering niet in voorbeelden.

Richtlijnen en instructiekenmerken die in onderdelen worden gebruikt, worden verder uitgelegd in dit artikel en andere artikelen van de documentatieset Blazor. Zie Razor syntaxisreferentie voor ASP.NET Corevoor algemene informatie over Razor syntaxis.

Onderdeelnaam, klassenaam en naamruimte

De naam van een onderdeel moet beginnen met een hoofdletter:

✔️ ondersteund:ProductDetail.razor

niet ondersteund:productDetail.razor

Algemene Blazor naamconventies die in de Blazor documentatie worden gebruikt, zijn onder andere:

  • Bestandspaden en bestandsnamen maken gebruik van Pascal-case† en worden weergegeven voordat codevoorbeelden worden weergegeven. Als er een pad aanwezig is, wordt de standaardlocatie van de map aangegeven. Components/Pages/ProductDetail.razor geeft bijvoorbeeld aan dat het ProductDetail onderdeel een bestandsnaam van ProductDetail.razor heeft en zich in de map Pages van de map Components van de app bevindt.
  • Bestandspaden voor componenten van routeerbare onderdelen komen overeen met hun URL's in kebab case, waarbij afbreekstreepjes worden gebruikt tussen woorden in de routesjabloon van een onderdeel. Een ProductDetail-onderdeel met een routesjabloon van /product-detail (@page "/product-detail") wordt bijvoorbeeld aangevraagd in een browser op de relatieve URL /product-detail.

†Pascal case (Upper Camel Case) is een naamgevingsconventie zonder spaties en interpunctie, waarbij de eerste letter van elk woord een hoofdletter heeft, inclusief het eerste woord.
‡Kebab case is een naamgevingsconventie zonder spaties en leestekens, die gebruikmaakt van kleine letters en streepjes tussen woorden.

Onderdelen zijn gewone C#-klassen en kunnen overal binnen een project worden geplaatst. Onderdelen die webpagina's produceren, bevinden zich meestal in de map Components/Pages. Onderdelen die geen pagina zijn, worden vaak in de Components map geplaatst of in een aangepaste map die aan het project is toegevoegd.

Normaal gesproken wordt de naamruimte van een onderdeel afgeleid van de hoofdnaamruimte van de app en de locatie (map) van het onderdeel in de app. Als de hoofdnaamruimte van de app BlazorSample is en het Counter onderdeel zich in de map Components/Pages bevindt:

  • De naamruimte van het Counter-onderdeel is BlazorSample.Components.Pages.
  • De volledig gekwalificeerde typenaam van het onderdeel is BlazorSample.Components.Pages.Counter.

Voor aangepaste mappen die onderdelen bevatten, voegt u een @using-instructie toe aan het bovenliggende onderdeel of aan het _Imports.razor-bestand van de app. In het volgende voorbeeld worden onderdelen in de map AdminComponents beschikbaar gemaakt:

@using BlazorSample.AdminComponents

Notitie

@using richtlijnen in het bestand _Imports.razor worden alleen toegepast op Razor bestanden (.razor), niet C#-bestanden (.cs).

Gealiaseerde using-verklaringen worden ondersteund. In het volgende voorbeeld wordt de openbare WeatherForecast klasse van het GridRendering-onderdeel beschikbaar gesteld als WeatherForecast in een onderdeel elders in de app:

@using WeatherForecast = Components.Pages.GridRendering.WeatherForecast

Er kan ook naar onderdelen worden verwezen met behulp van hun volledig gekwalificeerde namen, waarvoor geen @using-instructie is vereist. In het volgende voorbeeld wordt rechtstreeks verwezen naar het ProductDetail onderdeel in de map AdminComponents/Pages van de app:

<BlazorSample.AdminComponents.Pages.ProductDetail />

De naamruimte van een onderdeel dat is gemaakt met Razor is gebaseerd op het volgende (in volgorde van prioriteit):

  • De @namespace richtlijn in de opmaak van het bestand Razor (bijvoorbeeld @namespace BlazorSample.CustomNamespace).
  • De RootNamespace van het project in het projectbestand (bijvoorbeeld <RootNamespace>BlazorSample</RootNamespace>).
  • De projectnamespace en het pad van de hoofdmap van het project naar de component. Het framework lost bijvoorbeeld {PROJECT NAMESPACE}/Components/Pages/Home.razor op met een projectnaamruimte van BlazorSample naar de naamruimte BlazorSample.Components.Pages voor het Home-onderdeel. {PROJECT NAMESPACE} is de projectnaamruimte. Onderdelen volgen de bindingsregels voor C#-namen. Voor het Home-onderdeel in dit voorbeeld zijn de onderdelen binnen de scope alle componenten:
    • Components/Pagesin dezelfde map.
    • De onderdelen in de hoofdmap van het project die niet expliciet een andere naamruimte opgeven.

Hieronder worden niet ondersteund:

  • De global:: kwalificatie.
  • Gedeeltelijk gekwalificeerde namen. U kunt bijvoorbeeld geen @using BlazorSample.Components toevoegen aan een onderdeel en vervolgens verwijzen naar het NavMenu onderdeel in de map Components/Layout van de app (Components/Layout/NavMenu.razor) met <Layout.NavMenu></Layout.NavMenu>.

De naam van een onderdeel moet beginnen met een hoofdletter:

✔️ ondersteund:ProductDetail.razor

niet ondersteund:productDetail.razor

Algemene Blazor naamconventies die in de Blazor documentatie worden gebruikt, zijn onder andere:

  • Bestandspaden en bestandsnamen maken gebruik van Pascal-case† en worden weergegeven voordat codevoorbeelden worden weergegeven. Als er een pad aanwezig is, wordt de standaardlocatie van de map aangegeven. Pages/ProductDetail.razor geeft bijvoorbeeld aan dat het ProductDetail onderdeel een bestandsnaam van ProductDetail.razor heeft en zich in de map Pages van de app bevindt.
  • Bestandspaden voor routeerbare componenten komen overeen met hun URL's in kebab-case, waarbij er streepjes tussen de woorden in de routesjabloon van een component staan. Een ProductDetail-onderdeel met een routesjabloon van /product-detail (@page "/product-detail") wordt bijvoorbeeld aangevraagd in een browser op de relatieve URL /product-detail.

†Pascal case (UpperCamelCase) is een naamgevingsconventie zonder spaties en interpunctie waarbij de eerste letter van elk woord, inclusief het eerste, een hoofdletter heeft.
‡Kebab case is een naamgevingsconventie zonder spaties en leestekens, die kleine letters en streepjes tussen woorden gebruikt.

Onderdelen zijn gewone C#-klassen en kunnen overal binnen een project worden geplaatst. Onderdelen die webpagina's produceren, bevinden zich meestal in de map Pages. Onderdelen die geen pagina zijn, worden vaak in de Shared map geplaatst of in een aangepaste map die aan het project is toegevoegd.

Normaal gesproken wordt de naamruimte van een onderdeel afgeleid van de hoofdnaamruimte van de app en de locatie (map) van het onderdeel in de app. Als de hoofdnaamruimte van de app BlazorSample is en het Counter onderdeel zich in de map Pages bevindt:

  • De naamruimte van het Counter-onderdeel is BlazorSample.Pages.
  • De volledig gekwalificeerde typenaam van het onderdeel is BlazorSample.Pages.Counter.

Voor aangepaste mappen die onderdelen bevatten, voegt u een @using-instructie toe aan het bovenliggende onderdeel of aan het _Imports.razor-bestand van de app. In het volgende voorbeeld worden onderdelen in de map AdminComponents beschikbaar gemaakt:

@using BlazorSample.AdminComponents

Notitie

@using richtlijnen in het bestand _Imports.razor worden alleen toegepast op Razor bestanden (.razor), niet C#-bestanden (.cs).

Aliassen voor using-instructies worden ondersteund. In het volgende voorbeeld wordt de openbare WeatherForecast klasse van het GridRendering-onderdeel beschikbaar gesteld als WeatherForecast in een onderdeel elders in de app:

@using WeatherForecast = Pages.GridRendering.WeatherForecast

Er kan ook naar onderdelen worden verwezen met behulp van hun volledig gekwalificeerde namen, waarvoor geen @using-instructie is vereist. In het volgende voorbeeld wordt rechtstreeks verwezen naar het ProductDetail onderdeel in de map Components van de app:

<BlazorSample.Components.ProductDetail />

De naamruimte van een onderdeel dat is gemaakt met Razor is gebaseerd op het volgende (in volgorde van prioriteit):

  • De @namespace directive in de markup van het Razor bestand (bijvoorbeeld @namespace BlazorSample.CustomNamespace).
  • De RootNamespace van het project in het projectbestand (bijvoorbeeld <RootNamespace>BlazorSample</RootNamespace>).
  • De naamruimte van het project en het pad van de hoofdmap van het project naar de component. Het framework lost bijvoorbeeld {PROJECT NAMESPACE}/Pages/Index.razor op met een projectnaamruimte van BlazorSample naar de naamruimte BlazorSample.Pages voor het Index-onderdeel. {PROJECT NAMESPACE} is de projectnaamruimte. Onderdelen volgen de bindingsregels voor C#-namen. Voor het Index-onderdeel in dit voorbeeld omvat de reikwijdte alle onderdelen.
    • In dezelfde map, Pages.
    • De onderdelen in de hoofdmap van het project die niet expliciet een andere namespace opgeven.

Hieronder worden niet ondersteund:

  • De global:: kwalificatie.
  • Gedeeltelijk gekwalificeerde namen. U kunt bijvoorbeeld geen @using BlazorSample toevoegen aan een onderdeel en vervolgens verwijzen naar het NavMenu onderdeel in de map Shared van de app (Shared/NavMenu.razor) met <Shared.NavMenu></Shared.NavMenu>.

Ondersteuning voor gedeeltelijke klassen

Onderdelen worden gegenereerd als C#-gedeeltelijke klassen en worden gemaakt met behulp van een van de volgende methoden:

  • Eén bestand bevat C#-code die is gedefinieerd in een of meer @code blokken, HTML-opmaak en Razor markeringen. Blazor projectsjablonen definiëren hun onderdelen met behulp van deze benadering met één bestand.
  • HTML- en Razor-markeringen worden in een Razor-bestand (.razor) geplaatst. C#-code wordt in een code-behind-bestand geplaatst dat is gedefinieerd als een gedeeltelijke klasse (.cs).

Notitie

Een opmaakmodel voor onderdelen waarmee onderdeelspecifieke stijlen worden gedefinieerd, is een afzonderlijk bestand (.css). Blazor CSS-isolatie wordt verderop beschreven in ASP.NET Core Blazor CSS-isolatie.

In het volgende voorbeeld ziet u het standaardonderdeel Counter met een @code blok in een app die is gegenereerd op basis van een Blazor projectsjabloon. Markeringen en C#-code bevinden zich in hetzelfde bestand. Dit is de meest voorkomende benadering bij het ontwerpen van onderdelen.

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++;
    }
}

Met het volgende Counter onderdeel splitst u HTML van de presentatie en Razor markeringen uit de C#-code met behulp van een bestand achter code met een gedeeltelijke klasse. Het splitsen van de markeringen uit de C#-code wordt door sommige organisaties en ontwikkelaars bevoordeeld om hun onderdeelcode te ordenen op basis van hoe ze liever werken. De UI-expert van de organisatie kan bijvoorbeeld onafhankelijk werken aan de presentatielaag, terwijl een andere ontwikkelaar zich bezighoudt met de C#-logica van het onderdeel. De aanpak is ook handig bij het werken met automatisch gegenereerde code of brongeneratoren. Zie Partial Classes and Methods (C# Programming Guide)voor meer informatie.

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++;
        }
    }
}

@using richtlijnen in het bestand _Imports.razor worden alleen toegepast op Razor bestanden (.razor), niet C#-bestanden (.cs). Voeg indien nodig naamruimten toe aan een gedeeltelijk klassebestand.

Typische naamruimten die worden gebruikt door onderdelen:

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;

Typische naamruimten bevatten ook de naamruimte van de app en de naamruimte die overeenkomt met de Components map van de app:

using BlazorSample;
using BlazorSample.Components;

Er kunnen ook extra mappen worden opgenomen, zoals de map Layout:

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;

Typische naamruimten bevatten ook de naamruimte van de app en de naamruimte die overeenkomt met de Shared map van de app:

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;

Typische naamruimten bevatten ook de naamruimte van de app en de naamruimte die overeenkomt met de Shared map van de app:

using BlazorSample;
using BlazorSample.Shared;

Een basisklasse opgeven

De @inherits-instructie wordt gebruikt om een basisklasse voor een onderdeel op te geven. In tegenstelling tot het gebruik van gedeeltelijke klassen, waarmee alleen markeringen van C#-logica worden gesplitst, kunt u met behulp van een basisklasse C#-code overnemen voor gebruik in een groep onderdelen die de eigenschappen en methoden van de basisklasse delen. Het gebruik van basisklassen vermindert coderedundantie in apps en is handig bij het leveren van basiscode van klassebibliotheken aan meerdere apps. Zie Overerving in C# en .NETvoor meer informatie.

In het volgende voorbeeld is de BlazorRocksBase1 basisklasse afgeleid van 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!";
}

Routering

Routering in Blazor wordt bereikt door een routesjabloon op te geven voor elk toegankelijk onderdeel in de app met een @page instructie. Wanneer een Razor-bestand met een @page-instructie wordt gecompileerd, krijgt de gegenereerde klasse een RouteAttribute die de routesjabloon opgeeft. Tijdens runtime zoekt de router naar onderdeelklassen met een RouteAttribute en wordt weergegeven welk onderdeel een routesjabloon heeft die overeenkomt met de aangevraagde URL.

Het volgende HelloWorld onderdeel maakt gebruik van een routesjabloon van /hello-worlden de weergegeven webpagina voor het onderdeel wordt bereikt op de relatieve 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>

Het voorgaande onderdeel wordt geladen in de browser op /hello-world ongeacht of u het onderdeel toevoegt aan de navigatie van de gebruikersinterface van de app. Optioneel kunnen onderdelen worden toegevoegd aan het NavMenu-onderdeel, zodat een koppeling naar het onderdeel wordt weergegeven in de navigatie op basis van de gebruikersinterface van de app.

Voor het voorgaande HelloWorld-onderdeel kunt u een NavLink-onderdeel toevoegen aan het NavMenu-onderdeel. Zie ASP.NET Core Blazor routering en navigatievoor meer informatie, waaronder beschrijvingen van de NavLink en NavMenu onderdelen.

Opmaak

De gebruikersinterface van een onderdeel wordt gedefinieerd met behulp van Razor syntaxis, die bestaat uit Razor markeringen, C# en HTML. Wanneer een app wordt gecompileerd, worden de HTML-opmaak en de C#-renderinglogica geconverteerd naar een onderdeelklasse. De naam van de gegenereerde klasse komt overeen met de naam van het bestand.

Leden van de onderdeelklasse worden gedefinieerd in een of meer @code blokken. In @code blokken wordt de onderdeelstatus opgegeven en verwerkt met C#:

  • Initialisators voor eigenschappen en velden.
  • Parameterwaarden van argumenten die worden doorgegeven door bovenliggende onderdelen en routeparameters.
  • Methoden voor het verwerken van gebruikersevenementen, levenscyclus-gebeurtenissen en aangepaste onderdeellogica.

Onderdeelleden worden gebruikt in renderinglogica met behulp van C#-expressies die beginnen met het @ symbool. Een C#-veld wordt bijvoorbeeld weergegeven door het voorvoegsel @ op de veldnaam. Het volgende Markup onderdeel evalueert en rendert:

  • headingFontStyle voor de CSS-eigenschapswaarde font-style van het kopelement.
  • headingText voor de inhoud van het kopelement.

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!";
}

Notitie

Voorbeelden in de Blazor documentatie geven de private toegangsmodifier voor privéleden op. Privéleden zijn beperkt tot de klassen van een component. C# gaat er echter van uit dat de private toegangsmodifier geldt wanneer er geen andere toegangsmodifier aanwezig is, dus het expliciet markeren van leden als "private" in uw eigen code is optioneel. Zie Toegangsmodifiers (C#-programmeerhandleiding)voor meer informatie over toegangsmodifiers.

Het Blazor framework verwerkt een component intern als een render tree, wat de combinatie is van het DOM van een component en het Cascading Style Sheet Object Model (CSSOM). Nadat het onderdeel in eerste instantie is gerenderd, wordt de renderstructuur van het onderdeel opnieuw gegenereerd als reactie op gebeurtenissen. Blazor vergelijkt de nieuwe renderstructuur met de vorige weergavestructuur en past eventuele wijzigingen aan de DOM van de browser toe voor weergave. Zie ASP.NET Core Razor component renderingvoor meer informatie.

Razor syntaxis voor C#-besturingsstructuren, -instructies en -instructiekenmerken zijn kleine letters (voorbeelden: @if, @code, @bind). Eigenschapsnamen zijn in hoofdletters geschreven (bijvoorbeeld: @Body voor LayoutComponentBase.Body).

Asynchrone methoden (async) bieden geen ondersteuning voor het retourneren van void

Het Blazor-framework houdt void-returnerende asynchrone methoden (async) niet bij. Als gevolg hiervan worden uitzonderingen niet gedetecteerd als void wordt geretourneerd. Zorg ervoor dat je altijd een Task retourneert vanuit asynchrone methoden.

Geneste onderdelen

Onderdelen kunnen andere onderdelen bevatten door ze te declareren met behulp van HTML-syntaxis. De opmaak voor het gebruik van een onderdeel ziet eruit als een HTML-tag waarbij de naam van de tag het onderdeeltype is.

Houd rekening met het volgende Heading onderdeel, dat door andere onderdelen kan worden gebruikt om een kop weer te geven.

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";
}

Met de volgende markeringen in het HeadingExample onderdeel wordt het voorgaande Heading onderdeel weergegeven op de locatie waar de <Heading /> tag wordt weergegeven.

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 />

Als een onderdeel een HTML-element bevat met een eerste letter in hoofdletters die niet overeenkomt met een onderdeelnaam binnen dezelfde naamruimte, wordt er een waarschuwing verzonden die aangeeft dat het element een onverwachte naam heeft. Als u een @using-instructie toevoegt voor de naamruimte van het onderdeel, wordt het onderdeel beschikbaar gesteld, waardoor de waarschuwing wordt opgelost. Zie de sectie componentnaam, klassenaam en naamruimte voor meer informatie.

Het voorbeeld van het Heading onderdeel dat in deze sectie wordt weergegeven, heeft geen @page instructie, dus het Heading onderdeel is niet rechtstreeks toegankelijk voor een gebruiker via een directe aanvraag in de browser. Elk onderdeel met een @page richtlijn kan echter worden genest in een ander onderdeel. Als het Heading-onderdeel rechtstreeks toegankelijk was door @page "/heading" boven aan het Razor bestand op te geven, wordt het onderdeel weergegeven voor browseraanvragen op zowel /heading als /heading-example.

Onderdeelparameters

Componentparameters geven gegevens door aan componenten en worden gedefinieerd met behulp van openbare C#-eigenschappen in de componentklasse met het [Parameter] kenmerk.

In het volgende ParameterChild onderdeel omvatten onderdeelparameters:

  • Ingebouwde referentietypen.

  • Een door de gebruiker gedefinieerd referentietype (PanelBody) om kaartinhoud van Bootstrap door te geven in Body.

    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">
        <p>@Body.Text</p>
        @if (Count is not null)
        {
            <p>The count is @Count.</p>
        }
    </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"
        };

    [Parameter]
    public int? Count { get; set; }
}
<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">
        <p>@Body.Text</p>
        @if (Count is not null)
        {
            <p>The count is @Count.</p>
        }
    </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"
        };
    
    [Parameter]
    public int? Count { get; set; }
}
<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">
        <p>@Body.Text</p>
        @if (Count is not null)
        {
            <p>The count is @Count.</p>
        }
    </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"
        };

    [Parameter]
    public int? Count { get; set; }
}
<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">
        <p>@Body.Text</p>
        @if (Count is not null)
        {
            <p>The count is @Count.</p>
        }
    </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"
        };

    [Parameter]
    public int? Count { get; set; }
}
<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">
        <p>@Body.Text</p>
        @if (Count is not null)
        {
            <p>The count is @Count.</p>
        }
    </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"
        };

    [Parameter]
    public int? Count { get; set; }
}
<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">
        <p>@Body.Text</p>
        @if (Count is not null)
        {
            <p>The count is @Count.</p>
        }
    </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"
        };

    [Parameter]
    public int? Count { get; set; }
}

Waarschuwing

Het opgeven van initiële waarden voor onderdeelparameters wordt ondersteund, maar maak geen onderdeel dat naar zijn eigen parameters schrijft nadat het onderdeel voor het eerst wordt weergegeven. Zie Overschrijven van parameters voorkomen in ASP.NET Core Blazorvoor meer informatie.

De onderdeelparameters van het ParameterChild-onderdeel kunnen worden ingesteld op argumenten in de HTML-tag waarmee een exemplaar van het ParameterChild onderdeel wordt weergegeven. Het volgende bovenliggende component geeft twee ParameterChild componenten weer.

  • Het eerste ParameterChild onderdeel wordt weergegeven zonder parameterargumenten op te geven.
  • Het tweede ParameterChild onderdeel ontvangt waarden voor Title en Body van het bovenliggende onderdeel, dat gebruikmaakt van een expliciete C#-expressie om de waarden van de eigenschappen van de PanelBodyin te stellen.

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" })" />

In de volgende gerenderde HTML-opmaak van de oudercomponent worden component ParameterChild standaardwaarden weergegeven wanneer de oudercomponent geen parameterwaarden doorgeeft. Wanneer het bovenliggende onderdeel parameterwaarden voor onderdelen bevat, vervangen ze de standaardwaarden van het ParameterChild-onderdeel.

Notitie

Voor de duidelijkheid worden de meeste weergegeven CSS-stijlklassen en sommige elementen niet weergegeven in de volgende weergegeven HTML-opmaak. Het belangrijkste concept dat in het volgende voorbeeld wordt gedemonstreerd, is dat het bovenliggende onderdeel waarden heeft toegewezen aan het onderliggende onderdeel met behulp van de onderdeelparameters.

<h1>Child component (without attribute values)</h1>

<div>Set By Child</div>
<div style="font-style:normal">
    <p>Card content set by child.</p>
</div>

<h1>Child component (with attribute values)</h1>

<div>Set by Parent</div>
<div style="font-style:italic">
    <p>Set by parent.</p>
</div>

Wijs een C#-veld, eigenschap of resultaat van een methode toe aan een onderdeelparameter als een HTML-kenmerkwaarde. De waarde van het kenmerk kan doorgaans elke C#-expressie zijn die overeenkomt met het type parameter. De waarde van het kenmerk kan eventueel beginnen met een Razor gereserveerd symbool @, maar dit is niet vereist.

Als de onderdeelparameter van het type tekenreeks is, wordt de kenmerkwaarde in plaats daarvan behandeld als een letterlijke C#-tekenreeks. Als u in plaats daarvan een C#-expressie wilt opgeven, gebruikt u het voorvoegsel @.

In het volgende bovenliggende onderdeel worden vier exemplaren van het voorgaande ParameterChild onderdeel weergegeven en worden de Title parameterwaarden ingesteld op:

  • De waarde van het veld title.
  • Het resultaat van de methode GetTitle C#.
  • De huidige lokale datum in lange notatie met ToLongDateString, waarbij een impliciete C#-expressiewordt gebruikt.
  • De eigenschap Title van het panelData object.

Het vijfde ParameterChild onderdeelexemplaar stelt ook de Count parameter in. Houd er rekening mee dat voor een string-getypte parameter een @ voorvoegsel is vereist om ervoor te zorgen dat een expressie niet wordt behandeld als letterlijke tekenreeks. Count is echter een nullable integer (System.Int32), zodat Count de waarde van count kan ontvangen zonder een @ voorvoegsel. U kunt een alternatieve codeconventie instellen die vereist dat ontwikkelaars in uw organisatie altijd het voorvoegsel @gebruiken. In beide gevallen raden we u aan een consistente benadering te gebruiken voor de manier waarop onderdeelparameters worden doorgegeven in Razor markeringen.

Aanhalingstekens rond parameterkenmerkwaarden zijn in de meeste gevallen optioneel volgens de HTML5-specificatie. Value=this wordt bijvoorbeeld ondersteund in plaats van Value="this". We raden u echter aan om aanhalingstekens te gebruiken, omdat het eenvoudiger is om te onthouden en veel te gebruiken in webtechnologieën.

In de documentatie ziet u codevoorbeelden:

  • Gebruik altijd aanhalingstekens. Voorbeeld: Value="this".
  • Gebruik het @ voorvoegsel niet met niet-literalen, tenzij dit is vereist. Voorbeeld: Count="count", waarbij count een variabele met een getaltype is. Count="@count" is een geldige stijlbenadering, maar de documentatie en voorbeelden volgen deze conventie niet.
  • Vermijd altijd @ voor letterlijke gegevens, buiten Razor expressies. Voorbeeld: IsFixed="true". Dit omvat trefwoorden (bijvoorbeeld this) en null, maar u kunt ze desgewenst gebruiken. IsFixed="@true" is bijvoorbeeld ongebruikelijk, maar wel ondersteund.

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" />

<ParameterChild Title="String literal title" Count="count" />

@code {
    private string title = "From Parent field";
    private PanelData panelData = new();
    private int count = 12345;

    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" />

<ParameterChild Title="String literal title" Count="count" />

@code {
    private string title = "From Parent field";
    private PanelData panelData = new();
    private int count = 12345;

    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" />

<ParameterChild Title="String literal title" Count="count" />

@code {
    private string title = "From Parent field";
    private PanelData panelData = new();
    private int count = 12345;

    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" />

<ParameterChild Title="String literal title" Count="count" />

@code {
    private string title = "From Parent field";
    private PanelData panelData = new();
    private int count = 12345;

    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" />

<ParameterChild Title="String literal title" Count="count" />

@code {
    private string title = "From Parent field";
    private PanelData panelData = new PanelData();
    private int count = 12345;

    private string GetTitle()
    {
        return "From Parent method";
    }

    private class PanelData
    {
        public string Title { get; set; } = "From Parent object";
    }
}

Notitie

Wanneer u een C#-lid toewijst aan een onderdeelparameter, moet u het HTML-kenmerk van de parameter niet vooraf laten gaan door @.

Juist (Title is een tekenreeksparameter, Count een genummerde parameter is):

<ParameterChild Title="@title" Count="count" />
<ParameterChild Title="@title" Count="@count" />

Onjuist:

<ParameterChild @Title="@title" @Count="count" />
<ParameterChild @Title="@title" @Count="@count" />

In tegenstelling tot Razor pagina's (.cshtml), kan Blazor geen asynchroon werk uitvoeren in een Razor-expressie tijdens het weergeven van een onderdeel. Dit komt doordat Blazor is ontworpen voor het weergeven van interactieve UIS's. In een interactieve gebruikersinterface moet het scherm altijd iets weergeven, zodat het niet zinvol is om de renderingstroom te blokkeren. In plaats daarvan wordt asynchroon werk uitgevoerd tijdens een van de asynchrone levenscyclusgebeurtenissen. Na elke asynchrone levenscyclus-gebeurtenis kan het onderdeel opnieuw worden weergegeven. De volgende Razor syntaxis wordt niet ondersteund:

<ParameterChild Title="await ..." />
<ParameterChild Title="@await ..." />

De code in het voorgaande voorbeeld genereert een compilerfout wanneer de app wordt gebouwd:

De operator 'await' kan alleen worden gebruikt binnen een asynchrone methode. U kunt deze methode markeren met de modifier 'async' en het retourtype wijzigen in 'Taak'.

Als u een waarde wilt verkrijgen voor de parameter Title in het voorgaande voorbeeld asynchroon, kan het onderdeel de OnInitializedAsync levenscyclus-gebeurtenisgebruiken, zoals in het volgende voorbeeld wordt gedemonstreert:

<ParameterChild Title="@title" />

@code {
    private string? title;
    
    protected override async Task OnInitializedAsync()
    {
        title = await ...;
    }
}

Zie ASP.NET Core Razor levenscyclus van onderdelen voor meer informatie.

Het gebruik van een expliciete Razor-expressie om tekst samen te voegen met een expressieresultaat voor toewijzing aan een parameter wordt niet ondersteund. In het volgende voorbeeld wordt gezocht naar het samenvoegen van de tekst 'Set by ' met de eigenschapswaarde van een object. Hoewel deze syntaxis wordt ondersteund op een Razor pagina (.cshtml), is deze niet geldig voor toewijzing aan de Title parameter van het kind in een onderdeel. De volgende Razor syntaxis wordt niet ondersteund:

<ParameterChild Title="Set by @(panelData.Title)" />

De code in het voorgaande voorbeeld genereert een compilerfout wanneer de app wordt gebouwd:

Onderdeelkenmerken bieden geen ondersteuning voor complexe inhoud (gemengde C# en markeringen).

Gebruik een methode, veld of eigenschap om de toewijzing van een samengestelde waarde te ondersteunen. In het volgende voorbeeld wordt de samenvoeging van 'Set by ' en de eigenschapswaarde van een object uitgevoerd in de C#-methode GetTitle:

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";
    }
}

Zie Razor syntaxisreferentie voor ASP.NET Corevoor meer informatie.

Waarschuwing

Het opgeven van initiële waarden voor onderdeelparameters wordt ondersteund, maar maak geen onderdeel dat naar zijn eigen parameters schrijft nadat het onderdeel voor het eerst wordt weergegeven. Zie Overschrijven van parameters voorkomen in ASP.NET Core Blazorvoor meer informatie.

Onderdeelparameters moeten worden gedeclareerd als automatische eigenschappen, wat betekent dat ze geen aangepaste logica mogen bevatten in hun get of set accessors. De volgende StartData eigenschap is bijvoorbeeld een automatische eigenschap:

[Parameter]
public DateTime StartData { get; set; }

Plaats geen aangepaste logica in de get of set accessor omdat componentparameters uitsluitend bedoeld zijn als kanaal voor een oudercomponent om informatie naar een kindcomponent over te dragen. Als een set accessor van een eigenschap van een onderliggend component logica bevat die zorgt voor her-rendering van het bovenliggende component, resulteert dit in een oneindige renderinglus.

Een ontvangen parameterwaarde transformeren:

  • Laat de parametereigenschap staan als een automatische eigenschap om de opgegeven onbewerkte gegevens weer te geven.
  • Maak een andere eigenschap of methode om de getransformeerde gegevens op te geven op basis van de parametereigenschap.

Overschrijf OnParametersSetAsync om een ontvangen parameter te transformeren telkens wanneer er nieuwe gegevens worden ontvangen.

Het schrijven van een initiële waarde naar een onderdeelparameter wordt ondersteund omdat initiële waardetoewijzingen geen invloed hebben op de automatische weergave van het Blazor. De volgende toewijzing van de huidige lokale DateTime met DateTime.Now aan StartData is geldige syntaxis in een onderdeel:

[Parameter]
public DateTime StartData { get; set; } = DateTime.Now;

Na de eerste toewijzing van DateTime.Nowmoet u geen waarde toewijzen aan StartData in ontwikkelaarscode. Zie Overschrijven van parameters voorkomen in ASP.NET Core Blazorvoor meer informatie.

Pas het kenmerk [EditorRequired] toe om een vereiste onderdeelparameter op te geven. Als er geen parameterwaarde is opgegeven, kunnen editors of buildhulpprogramma's waarschuwingen voor de gebruiker weergeven. Dit kenmerk is alleen geldig voor eigenschappen die ook zijn gemarkeerd met het kenmerk [Parameter]. De EditorRequiredAttribute wordt afgedwongen bij het ontwerpen en wanneer de app wordt gecompileerd. Het kenmerk wordt niet afgedwongen tijdens runtime en garandeert geen niet-null parameterwaarde.

[Parameter]
[EditorRequired]
public string? Title { get; set; }

Lijsten met kenmerken met één regel worden ook ondersteund:

[Parameter, EditorRequired]
public string? Title { get; set; }

Gebruik de required modifier niet of init accessor voor onderdelenparametereigenschappen. Componenten worden meestal geïnstantieerd en krijgen parameterwaarden toegewezen met behulp van reflectie, waarbij de garanties worden omzeild die init en required zijn ontworpen om te bieden. Gebruik in plaats daarvan het kenmerk [EditorRequired] om een vereiste onderdeelparameter op te geven.

Gebruik de init accessor niet op parameter-eigenschappen van componenten, omdat het instellen van componentparameterwaarden met ParameterView.SetParameterPropertiesreflectiegebruikt, waardoor de beperking van de init-only setter wordt omzeild. Gebruik het [EditorRequired] kenmerk om een vereiste onderdeelparameter op te geven.

Gebruik de init accessor niet voor onderdeelparametereigenschappen, omdat het instellen van parameterwaarden voor onderdelen met ParameterView.SetParameterPropertiesweerspiegelinggebruikt, waardoor de beperking voor alleen-init-setter wordt overgeslagen.

Tuples (API-documentatie) worden ondersteund voor onderdeelparameters en RenderFragment typen. In het volgende voorbeeld van een onderdeelparameter worden drie waarden in een Tupledoorgegeven:

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);
}

Benoemde tuples worden ondersteund, zoals je kunt zien in het volgende voorbeeld.

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);
}

Quote ©2005 Universal Pictures: Serenity (Nathan Fillion)

Tuples (API-documentatie) worden ondersteund voor onderdeelparameters en RenderFragment typen. In het volgende voorbeeld van een onderdeelparameter worden drie waarden in een Tupledoorgegeven:

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);
}

Benoemde tuples Worden ondersteund, zoals te zien is in het volgende voorbeeld:

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);
}

Quote ©2005 Universal Pictures: Serenity (Nathan Fillion)

Tuples (API-documentatie) worden ondersteund voor onderdeelparameters en RenderFragment typen. In het volgende voorbeeld van een onderdeelparameter worden drie waarden in een Tupledoorgegeven:

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);
}

Benoemde tuples worden ondersteund, zoals te zien is in het volgende voorbeeld:

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);
}

Quote ©2005 Universal Pictures: Serenity (Nathan Fillion)

Route parameters

Onderdelen kunnen routeparameters opgeven in de routesjabloon van de @page-instructie. De Blazor router gebruikt routeparameters om de bijbehorende onderdeelparameters in te vullen.

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; }
}

Zie de sectie Routeparameters van ASP.NET Core Blazor routering en navigatievoor meer informatie. Optionele routeparameters worden ook ondersteund en behandeld in dezelfde sectie. Voor informatie over catch-all routeparameters ({*pageRoute}), waarmee paden over meerdere mapgrenzen worden vastgelegd, zie de sectie catch-all routeparameters in ASP.NET Core Blazor routering en navigatie.

Voor meer informatie, zie de sectie Routeparameters van ASP.NET Core Blazor routering en navigatie. Optionele routeparameters worden niet ondersteund, dus er zijn twee @page richtlijnen vereist (zie de sectie Routeparameters voor meer informatie). Zie de catch-all routeparameters sectie van ASP.NET Core Blazor routering en navigatievoor informatie over de parameters voor alle routegegevens ({*pageRoute}), waarmee paden over meerdere mapgrenzen worden vastgelegd.

Waarschuwing

Met compressie, die standaard is ingeschakeld, vermijdt u het maken van beveiligde (geverifieerde/geautoriseerde) interactieve serveronderdelen die gegevens uit niet-vertrouwde bronnen weergeven. Niet-vertrouwde bronnen omvatten routeparameters, queryreeksen, gegevens uit JS interop en andere gegevensbronnen die een externe gebruiker kan beheren (databases, externe services). Voor meer informatie, zie ASP.NET Core BlazorSignalR-richtlijnen en richtlijnen voor dreigingsbeperking voor ASP.NET Core Blazor interactieve server-side rendering.

Fragmenten weergeven van onderliggende inhoud

Onderdelen kunnen de inhoud van een ander onderdeel instellen. Het toe te wijzen component biedt de inhoud tussen de openings- en sluitingslabels van het subcomponent.

In het volgende voorbeeld heeft het RenderFragmentChild onderdeel een ChildContent onderdeelparameter die een segment van de gebruikersinterface vertegenwoordigt dat moet worden weergegeven als een RenderFragment. De positie van ChildContent in de Razor opmaak van het onderdeel is de plaats waar de inhoud wordt weergegeven in de uiteindelijke HTML-uitvoer.

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; }
}

Belangrijk

De eigenschap die de inhoud van de RenderFragment ontvangt, moet conventioneel ChildContent worden genoemd.

event callbacks worden niet ondersteund voor RenderFragment.

Het volgende onderdeel biedt content voor het weergeven van de RenderFragmentChild door de content in de openings- en sluittags van het onderliggende onderdeel te plaatsen.

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>

Renderfragmenten worden gebruikt om onderliggende inhoud weer te geven in Blazor apps en worden beschreven met voorbeelden in de volgende artikelen en artikelsecties:

Notitie

Blazor framework's ingebouwde Razor-onderdelen dezelfde parameterconventie voor ChildContent onderdelen gebruiken om hun inhoud in te stellen. U kunt de onderdelen die kindinhoud instellen zien door te zoeken naar de componentparameter eigenschapsnaam ChildContent in de API documentatie (API filtert met de zoekterm "ChildContent").

Fragmenten weergeven voor herbruikbare renderinglogica

U kunt subcomponenten afzonderen als een manier om renderinglogica opnieuw te gebruiken. Definieer in het @code blok van een onderdeel een RenderFragment en geef het fragment zo vaak als nodig weer vanaf elke locatie:

@RenderWelcomeInfo

<p>Render the welcome info a second time:</p>

@RenderWelcomeInfo

@code {
    private RenderFragment RenderWelcomeInfo =  @<p>Welcome to your new app!</p>;
}

Zie Renderinglogica opnieuw gebruikenvoor meer informatie.

Lusvariabelen met componentparameters en kindinhoud

Voor het weergeven van onderdelen in een for lus is een lokale indexvariabele vereist als de variabele incrementele lus wordt gebruikt door de parameters van het onderdeel of RenderFragment onderliggende inhoud.

Houd rekening met het volgende RenderFragmentChild2 onderdeel met zowel een componentparameter (Id) als een renderfragment om onderliggende inhoud (ChildContent) weer te geven.

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; }
}

Wanneer u de component RenderFragmentChild2 weergeeft in een bovenliggende component, gebruikt u een lokale indexvariabele (ct in het volgende voorbeeld) in plaats van de lusvariabele (c) bij het toewijzen van de componentparameterwaarde en het opgeven van de inhoud van de onderliggende component:

@for (int c = 1; c < 4; c++)
{
    var ct = c;

    <RenderFragmentChild2 Id="@($"Child{ct}")">
        Count: @ct
    </RenderFragmentChild2>
}

U kunt ook een foreach lus gebruiken met Enumerable.Range in plaats van een for lus:

@foreach (var c in Enumerable.Range(1, 3))
{
    <RenderFragmentChild2 Id="@($"Child{c}")">
        Count: @c
    </RenderFragmentChild2>
}

Verwijzingen naar onderdelen vastleggen

Onderdeelverwijzingen bieden een manier om naar een onderdeelexemplaar te verwijzen voor het uitvoeren van opdrachten. Een componentreferentie vastleggen:

  • Voeg een @ref kenmerk toe aan de subcomponent.
  • Definieer een veld met hetzelfde type als het onderliggende onderdeel.

Wanneer de component wordt weergegeven, wordt het veld gevuld met de componenteenheid. Vervolgens kunt u .NET-methoden aanroepen op het exemplaar.

Houd rekening met het volgende ReferenceChild onderdeel dat een bericht registreert wanneer de ChildMethod wordt aangeroepen.

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);
    }
}

Een componentverwijzing wordt pas ingevuld nadat het component is gerenderd en de uitvoer het element van ReferenceChildbevat. Totdat het onderdeel gerenderd is, is er niets om naar te verwijzen. Probeer niet rechtstreeks een componentmethode waarnaar wordt verwezen aan te roepen aan een gebeurtenishandler (bijvoorbeeld @onclick="childComponent!.ChildMethod(5)") omdat de verwijzingsvariabele mogelijk niet wordt toegewezen op het moment dat de klikgebeurtenis is toegewezen.

Als u onderdeelverwijzingen wilt bewerken nadat het onderdeel klaar is met renderen, gebruikt u de OnAfterRender- of OnAfterRenderAsync methoden.

In het volgende voorbeeld wordt het voorgaande ReferenceChild onderdeel gebruikt.

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);
    }
}

Tijdens het vastleggen van onderdeelverwijzingen wordt een vergelijkbare syntaxis gebruikt als het vastleggen van elementverwijzingen, is het vastleggen van onderdeelverwijzingen geen JavaScript-interop-functie. Onderdeelverwijzingen worden niet doorgegeven aan JavaScript-code. Onderdeelverwijzingen worden alleen gebruikt in .NET-code.

Belangrijk

Gebruik geen onderdeelverwijzingen om de status van onderliggende componenten te wijzigen. Gebruik in plaats daarvan normale declaratieve componentparameters om gegevens door te geven aan onderliggende onderdelen. Het gebruik van componentparameters resulteert in onderliggende componenten die automatisch op de juiste momenten opnieuw gerenderd worden. Zie de sectie componentparameters en het artikel ASP.NET Core Blazor data binding voor meer informatie.

Een kenmerk toepassen

Kenmerken kunnen worden toegepast op onderdelen met de @attribute directive. In het volgende voorbeeld wordt het kenmerk [Authorize] toegepast op de klasse van het onderdeel:

@page "/"
@attribute [Authorize]

Kenmerken van voorwaardelijke HTML-elementen en DOM-eigenschappen

Blazor gaat over op de volgende algemene gedragingen:

  • Voor HTML-attributen stelt Blazor het attribuut in of verwijdert het voorwaardelijk op basis van de .NET-waarde. Als de .NET-waarde is false of null, wordt het kenmerk niet ingesteld of verwijderd als deze eerder is ingesteld.
  • Voor DOM-eigenschappen, zoals checked of value, stelt Blazor de DOM-eigenschap in op basis van de .NET-waarde. Als de .NET-waarde is false of null, wordt de dom-eigenschap opnieuw ingesteld op een standaardwaarde.

Welke Razor syntaxiskenmerken overeenkomen met HTML-kenmerken en welke overeenkomen met DOM-eigenschappen blijft ongedocumenteerd omdat dit een framework-implementatiedetail is dat zonder kennisgeving kan worden gewijzigd.

Waarschuwing

Sommige HTML-kenmerken, zoals aria-pressed, moeten een tekenreekswaarde hebben van 'true' of 'false'. Omdat ze een tekenreekswaarde en niet een booleaanse waarde vereisen, moet u een .NET-string gebruiken en geen bool voor hun waarde. Dit is een vereiste die is ingesteld door browser-DOM-API's.

Onbewerkte HTML

Tekenreeksen worden normaal gesproken weergegeven met DOM-tekstknooppunten, wat betekent dat alle markeringen die ze kunnen bevatten, worden genegeerd en behandeld als letterlijke tekst. Als u onbewerkte HTML wilt weergeven, verpakt u de HTML-inhoud in een MarkupString waarde. De waarde wordt geparseerd als HTML of SVG en ingevoegd in de DOM.

Waarschuwing

Het weergeven van onbewerkte HTML die is samengesteld op basis van een niet-vertrouwde bron, is een beveiligingsrisico en moet altijd worden vermeden.

In het volgende voorbeeld ziet u hoe u het type MarkupString gebruikt om een blok statische HTML-inhoud toe te voegen aan de weergegeven uitvoer van een onderdeel.

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>";
}

sjablonen voor Razor

Renderfragmenten kunnen worden gedefinieerd met behulp van Razor sjabloonsyntaxis om een UI-fragment te definiëren. Razor sjablonen gebruiken de volgende indeling:

@<{HTML tag}>...</{HTML tag}>

In het volgende voorbeeld ziet u hoe u waarden voor RenderFragment en RenderFragment<TValue> kunt opgeven en sjablonen rechtstreeks in een onderdeel kunt weergeven. Renderfragmenten kunnen ook worden doorgegeven als argumenten voor sjabloononderdelen.

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; }
    }
}

Uitvoer van de voorgaande code weergegeven:

<p>The time is 4/19/2021 8:54:46 AM.</p>
<p>Pet: Nutty Rex</p>

Statische assets

Blazor volgt de conventie van ASP.NET Core-apps voor statische assets. Statische assets bevinden zich in de map web root (wwwroot) van het project of mappen onder de map wwwroot.

Gebruik een basis-relatief pad (/) om te verwijzen naar de webroot voor een statisch element. In het volgende voorbeeld bevindt logo.png zich fysiek in de map {PROJECT ROOT}/wwwroot/images. {PROJECT ROOT} is de projectroot van de app.

<img alt="Company logo" src="/images/logo.png" />

Onderdelen geen ondersteuning voor tilde-slash-notatie (~/).

Zie Host en implementeer ASP.NET Core Blazorvoor meer informatie over het instellen van het basispad van een app.

Tag Helpers worden niet ondersteund in componenten

Tag Helpers worden niet ondersteund in onderdelen. Als u Tag Helper-functionaliteit wilt bieden in Blazor, maakt u een onderdeel met dezelfde functionaliteit als de Tag Helper en gebruikt u het onderdeel.

SVG-afbeeldingen (Scalable Vector Graphics)

Omdat Blazor HTML weergeeft, worden door de browser ondersteunde afbeeldingen, waaronder SVG-afbeeldingen (Scalable Vector Graphics) (.svg), ondersteund via de <img> tag:

<img alt="Example image" src="image.svg" />

Op dezelfde manier worden SVG-afbeeldingen ondersteund in de CSS-regels van een opmaakmodelbestand (.css):

.element-class {
    background-image: url("image.svg");
}

Blazor ondersteunt het <foreignObject>-element om willekeurige HTML in een SVG weer te geven. De markering kan willekeurige HTML, een RenderFragmentof een Razor-onderdeel vertegenwoordigen.

In het volgende voorbeeld ziet u:

  • Weergave van een string (@message).
  • Tweerichtingsbinding met een <input>-element en een value veld.
  • Een Robot-onderdeel.
<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;
}

Gedrag van rendering van witruimte

Tenzij de @preservewhitespace instructie wordt gebruikt met een waarde van true, wordt extra witruimte verwijderd als:

  • Voorloop of volging binnen een element.
  • Voorloop of afsluiting binnen een RenderFragment/RenderFragment<TValue> parameter (bijvoorbeeld inhoud van een onderliggend element dat aan een ander onderdeel is doorgegeven).
  • Het wordt voorafgegaan aan of volgt een C#-codeblok, zoals @if of @foreach.

Verwijdering van witruimten kan van invloed zijn op de weergegeven uitvoer bij het gebruik van een CSS-regel, zoals white-space: pre. Voer een van de volgende acties uit om deze prestatieoptimalisatie uit te schakelen en de witruimte te behouden:

  • Voeg de @preservewhitespace true-instructie toe bovenaan het Razor-bestand (.razor) om de voorkeur toe te passen op een specifiek onderdeel.
  • Voeg de @preservewhitespace true-instructie toe in een _Imports.razor-bestand om de voorkeur toe te passen op een submap of op het hele project.

In de meeste gevallen is er geen actie vereist, omdat apps zich doorgaans normaal blijven gedragen (maar sneller). Als het verwijderen van witruimte een renderingprobleem voor een bepaald onderdeel veroorzaakt, gebruikt u @preservewhitespace true in dat onderdeel om deze optimalisatie uit te schakelen.

Witruimte wordt bewaard in de bronmarkeringen van een onderdeel. Tekst met alleen witruimte wordt weergegeven in de DOM van de browser, zelfs als er geen visueel effect is.

Houd rekening met de volgende onderdeelmarkeringen:

<ul>
    @foreach (var item in Items)
    {
        <li>
            @item.Text
        </li>
    }
</ul>

In het voorgaande voorbeeld wordt de volgende overbodige witruimte weergegeven:

  • Buiten het @foreach-codeblok.
  • Rond het <li> element.
  • Rond de @item.Text uitvoer.

Een lijst met 100 items resulteert in meer dan 400 witruimtegebieden. Geen van de extra witruimte is visueel van invloed op de gerenderde uitvoer.

Bij het weergeven van statische HTML voor onderdelen blijft witruimte binnen een tag niet behouden. Bekijk bijvoorbeeld de weergegeven uitvoer van de volgende <img> tag in een onderdeelbestand Razor bestand (.razor):

<img     alt="Example image"   src="img.png"     />

Witruimte blijft niet behouden ten opzichte van de voorgaande markeringen:

<img alt="Example image" src="img.png" />

Hoofdonderdeel

Een hoofdonderdeel Razor (hoofdonderdeel) is het eerste onderdeel dat is geladen van een onderdeelhiërarchie die door de app is gemaakt.

In een app die is gemaakt op basis van de Blazor Web App projectsjabloon, wordt het App-onderdeel (App.razor) opgegeven als het standaardhoofdonderdeel door de typeparameter die is gedeclareerd voor de aanroep van MapRazorComponents<TRootComponent> in het Program-bestand aan de serverzijde. In het volgende voorbeeld ziet u het gebruik van het App-onderdeel als hoofdonderdeel. Dit is de standaardinstelling voor een app die is gemaakt op basis van de Blazor-projectsjabloon:

app.MapRazorComponents<App>();

Notitie

Het interactief maken van een hoofdonderdeel, zoals het App-onderdeel, wordt niet ondersteund.

In een app die is gemaakt op basis van de Blazor Server projectsjabloon, wordt het App onderdeel (App.razor) opgegeven als het standaardhoofdonderdeel in Pages/_Host.cshtml met behulp van de Component Tag Helper:

<component type="typeof(App)" render-mode="ServerPrerendered" />

In een app die is gemaakt op basis van de Blazor WebAssembly projectsjabloon, wordt het App-onderdeel (App.razor) opgegeven als het standaardhoofdonderdeel in het Program-bestand:

builder.RootComponents.Add<App>("#app");

In de voorgaande code geeft de CSS-selector, #app, aan dat het App onderdeel is opgegeven voor de <div> in wwwroot/index.html met een id van app:

<div id="app">...</app>

MVC- en Razor Pages-apps kunnen ook de Component Tag Helper gebruiken om statisch gerenderde Blazor WebAssembly rootcomponenten te registreren.

<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />

Statische gerenderde onderdelen kunnen alleen aan de app worden toegevoegd. Ze kunnen achteraf niet worden verwijderd of bijgewerkt.

Zie de volgende bronnen voor meer informatie:

IHttpContextAccessor/HttpContext

IHttpContextAccessor over het algemeen moet worden vermeden met interactieve rendering, omdat een geldige HttpContext niet altijd beschikbaar is.

IHttpContextAccessor kunnen worden gebruikt voor onderdelen die statisch worden weergegeven op de server. We raden u echter aan deze indien mogelijk te vermijden.

HttpContext kan worden gebruikt als een trapsgewijze parameter alleen in statisch gerenderde hoofdonderdelen voor algemene taken, zoals het inspecteren en wijzigen van headers of andere eigenschappen in het App onderdeel (Components/App.razor). De waarde wordt altijd null voor interactieve rendering.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Voor scenario's waarbij de HttpContext vereist is in interactieve onderdelen, raden we u aan om de gegevens via de status van een permanent onderdeel vanaf de server te laten stromen. Zie ASP.NET Core-serverzijde en Blazor Web App aanvullende beveiligingsscenario'svoor meer informatie.

Gebruik IHttpContextAccessor/HttpContext niet direct of indirect in de Razor onderdelen van Blazor-apps aan de serverzijde. Blazor apps worden uitgevoerd buiten de context van de ASP.NET Core-pijplijn. De HttpContext is niet gegarandeerd beschikbaar in de IHttpContextAccessoren er wordt niet gegarandeerd dat HttpContext de context behoudt waarmee de Blazor-app is gestart.

De aanbevolen methode voor het doorgeven van de status van de aanvraag aan de Blazor-app is via de parameters van het hoofdonderdeel tijdens de eerste rendering van de app. De app kan de gegevens ook kopiëren naar een gescopeerde service tijdens de initialisatiecyclus van het hoofdonderdeel, zodat deze in de hele app kunnen worden gebruikt. Zie ASP.NET Core-serverzijde en Blazor Web App aanvullende beveiligingsscenario'svoor meer informatie.

Een essentieel aspect van Blazor beveiliging aan de serverzijde is dat de gebruiker die aan een bepaald circuit is gekoppeld, op een bepaald moment kan worden bijgewerkt nadat het Blazor circuit tot stand is gebracht, maar de IHttpContextAccessorniet wordt bijgewerkt. Zie ASP.NET Core-serverzijde en Blazor Web App aanvullende beveiligingsscenario'svoor meer informatie over het aanpakken van deze situatie met aangepaste services.