Bagikan melalui


Komponen Razor ASP.NET Core

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Artikel ini menjelaskan cara membuat dan menggunakan komponen Razor di aplikasi Blazor, termasuk panduan tentang sintaks Razor, penamaan komponen, namespace layanan, dan parameter komponen.

Komponen Razor

Blazor aplikasi dibangun menggunakan Razor komponen, secara informal dikenal sebagai Blazor komponen atau hanya komponen. Komponen adalah bagian mandiri dari antarmuka pengguna (UI) dengan logika pemrosesan untuk mengaktifkan perilaku dinamis. Komponen dapat ditumpuk, digunakan kembali, dibagikan di antara proyek, dan digunakan di aplikasi MVC dan Razor Pages.

Komponen dirender menjadi representasi dalam memori Model Objek Dokumen (DOM) browser yang disebut pohon render, yang digunakan untuk memperbarui UI dengan cara yang fleksibel dan efisien.

Meskipun "Razor komponen" berbagi beberapa penamaan dengan teknologi penyajian konten ASP.NET Core lainnya, Razor komponen harus dibedakan dari berbagai fitur berikut di ASP.NET Core:

Penting

Saat menggunakan , sebagian Blazor besar komponen contoh dokumentasi memerlukan interaktivitas untuk berfungsi dan menunjukkan konsep yang dibahas oleh artikel.Blazor Web App Saat Anda menguji komponen contoh yang disediakan oleh artikel, pastikan aplikasi mengadopsi interaktivitas global atau komponen mengadopsi mode render interaktif. Informasi selengkapnya tentang subjek ini disediakan oleh mode render ASP.NET CoreBlazor, yang merupakan artikel berikutnya dalam daftar isi setelah artikel ini.

Kelas komponen

Komponen diimplementasikan menggunakan kombinasi markup C# dan HTML dalam file komponen Razor dengan ekstensi file .razor.

ComponentBase adalah kelas dasar untuk komponen yang dijelaskan oleh Razor file komponen. ComponentBase mengimplementasikan abstraksi komponen terendah, IComponent antarmuka. ComponentBase menentukan properti komponen dan metode untuk fungsionalitas dasar, misalnya, untuk memproses serangkaian peristiwa siklus hidup komponen bawaan.

ComponentBase di dotnet/aspnetcore sumber referensi: Sumber referensi berisi komentar tambahan pada peristiwa siklus hidup bawaan. Namun, perlu diingat bahwa implementasi internal fitur komponen dapat berubah kapan saja tanpa pemberitahuan.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Pengembang biasanya membuat komponen dari Razor file komponen (.razor) atau mendasarkan komponennya pada ComponentBase, tetapi komponen juga dapat dibangun dengan menerapkan IComponent.Razor Komponen yang dibangun pengembang yang diterapkan IComponent dapat mengambil kontrol tingkat rendah atas penyajian dengan biaya harus memicu penyajian secara manual dengan peristiwa dan metode siklus hidup yang harus dibuat dan dikelola pengembang.

Konvensi tambahan yang diadopsi oleh Blazor kode contoh dokumentasi dan aplikasi sampel ditemukan dalam dasar-dasar ASP.NET CoreBlazor.

Razor sintaks

Komponen menggunakan sintaks Razor. Dua fitur Razor banyak digunakan oleh komponen, arahan dan atribut arahan. Ini adalah kata kunci khusus yang diawali dengan @, yang muncul di markup Razor:

  • Arahan: Mengubah cara markup komponen dikompilasi atau fungsi. Misalnya, direktif @page menentukan komponen yang dapat dirutekan dengan templat rute yang dapat dijangkau langsung oleh permintaan pengguna di browser pada URL tertentu.

    Menurut konvensi, arahan komponen di bagian atas definisi komponen (.razor file) ditempatkan dalam urutan yang konsisten. Untuk arahan berulang, arahan ditempatkan menurut abjad menurut namespace atau jenis, kecuali @using direktif, yang memiliki urutan tingkat kedua khusus.

    Urutan berikut diadopsi oleh Blazor aplikasi sampel dan dokumentasi. Komponen yang Blazor disediakan oleh templat proyek mungkin berbeda dari urutan berikut dan menggunakan format yang berbeda. Misalnya, Blazor komponen kerangka kerja Identity mencakup baris kosong antara blok arahan @using dan blok arahan @inject . Anda bebas menggunakan skema dan format pemesanan kustom di aplikasi Anda sendiri.

    Dokumentasi dan contoh urutan direktif aplikasi Razor :

    • @page
    • @rendermode (.NET 8 atau yang lebih baru)
    • @using
      • System namespace (urutan alfabet)
      • Microsoft namespace (urutan alfabet)
      • Namespace API pihak ketiga (urutan alfabet)
      • Namespace aplikasi (urutan alfabet)
    • Direktif lain (urutan alfabet)

    Tidak ada baris kosong yang muncul di antara arahan. Satu baris kosong muncul antara direktif dan baris Razor pertama markup.

    Contoh:

    @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>
    
    ...
    
  • Atribut direktif: Mengubah cara elemen komponen dikompilasi atau fungsi.

    Contoh:

    <input @bind="episodeId" />
    

    Anda dapat mengawali nilai atribut direktif dengan simbol at (@) untuk ekspresi non-eksplisit Razor (@bind="@episodeId"), tetapi kami tidak merekomendasikannya, dan dokumen tidak mengadopsi pendekatan dalam contoh.

Atribut arahan dan arahan yang digunakan dalam komponen dijelaskan lebih lanjut dalam artikel ini dan artikel lain dari rangkaian dokumentasi Blazor. Untuk informasi umum tentang sintaks Razor, lihat referensi sintaks Razor untuk ASP.NET Core.

Nama komponen, nama kelas, dan namespace

Nama komponen harus dimulai dengan karakter huruf besar:

Didukung: ProductDetail.razor

Tidak didukung: productDetail.razor

Konvensi penamaan Blazor umum yang digunakan di seluruh dokumentasi Blazor meliputi:

  • Jalur file dan nama file menggunakan kasus Pascal† dan muncul sebelum menampilkan contoh kode. Jika ada jalur, jalur menunjukkan lokasi folder umum. Misalnya, Components/Pages/ProductDetail.razor menunjukkan bahwa ProductDetail komponen memiliki nama ProductDetail.razor file dan berada di Pages folder Components folder aplikasi.
  • Jalur file komponen untuk komponen yang dapat dirutekan cocok dengan URL mereka dalam kasus kebab‡ dengan tanda hubung yang muncul di antara kata-kata dalam templat rute komponen. Misalnya, komponen ProductDetail dengan template rute /product-detail (@page "/product-detail") diminta di browser di URL relatif /product-detail.

†Pascal case (camel case dengan huruf besar) adalah konvensi penamaan tanpa spasi dan tanda baca dan dengan huruf pertama dari setiap kata dikapitalisasi, termasuk kata pertama.
‡Kasus Kebab adalah konvensi penamaan tanpa spasi dan tanda baca yang menggunakan huruf kecil dan tanda hubung antar kata.

Komponen adalah kelas C# biasa dan dapat ditempatkan di mana saja dalam suatu proyek. Komponen yang menghasilkan halaman web biasanya berada di folder Components/Pages. Komponen non-halaman sering ditempatkan di folder Components atau folder kustom yang ditambahkan ke proyek.

Biasanya, namespace layanan komponen berasal dari namespace layanan akar aplikasi dan lokasi komponen (folder) di dalam aplikasi. Jika namespace layanan akar aplikasi adalah BlazorSample dan komponen Counter berada di folder Components/Pages:

  • Namespace layanan komponen Counter adalah BlazorSample.Components.Pages.
  • Nama jenis komponen yang sepenuhnya memenuhi syarat adalah BlazorSample.Components.Pages.Counter.

Untuk folder kustom yang menyimpan komponen, tambahkan arahan @using ke komponen induk atau ke file _Imports.razor aplikasi. Contoh berikut membuat komponen dalam folder AdminComponents tersedia:

@using BlazorSample.AdminComponents

Catatan

Arahan @using dalam file _Imports.razor hanya diterapkan pada file Razor (.razor), bukan file C# (.cs).

Pernyataan alias using didukung. Dalam contoh berikut, kelas GridRendering publik WeatherForecast komponen tersedia seperti WeatherForecast di komponen di tempat lain di aplikasi:

@using WeatherForecast = Components.Pages.GridRendering.WeatherForecast

Komponen juga dapat direferensikan menggunakan nama yang sepenuhnya memenuhi syarat, yang tidak memerlukan arahan @using. Contoh berikut secara langsung merujuk komponen ProductDetail di folder AdminComponents/Pages aplikasi:

<BlazorSample.AdminComponents.Pages.ProductDetail />

Namespace layanan komponen yang dibuat dengan Razor didasarkan pada hal berikut (dalam urutan prioritas):

  • Arahan @namespace di markup file Razor (misalnya, @namespace BlazorSample.CustomNamespace).
  • RootNamespace proyek dalam file proyek (misalnya, <RootNamespace>BlazorSample</RootNamespace>).
  • Namespace layanan proyek dan jalur dari akar proyek ke komponen. Misalnya, kerangka kerja diselesaikan {PROJECT NAMESPACE}/Components/Pages/Home.razor dengan namespace BlazorSample proyek ke namespace BlazorSample.Components.Pages layanan untuk Home komponen. {PROJECT NAMESPACE} adalah namespace proyek. Komponen mengikuti aturan pengikatan nama C#. Home Untuk komponen dalam contoh ini, komponen dalam cakupan adalah semua komponen:
    • Dalam folder yang sama, Components/Pages.
    • Komponen di akar proyek yang tidak secara eksplisit menentukan namespace layanan yang berbeda.

Berikut ini tidak didukung:

  • Kualifikasi global::.
  • Nama yang memenuhi sebagian syarat. Misalnya, Anda tidak dapat menambahkan @using BlazorSample.Components ke komponen lalu merujuk komponen NavMenu di folder Components/Layout aplikasi (Components/Layout/NavMenu.razor) dengan <Layout.NavMenu></Layout.NavMenu>.

Nama komponen harus dimulai dengan karakter huruf besar:

Didukung: ProductDetail.razor

Tidak didukung: productDetail.razor

Konvensi penamaan Blazor umum yang digunakan di seluruh dokumentasi Blazor meliputi:

  • Jalur file dan nama file menggunakan kasus Pascal† dan muncul sebelum menampilkan contoh kode. Jika ada jalur, jalur menunjukkan lokasi folder umum. Misalnya, Pages/ProductDetail.razor menunjukkan bahwa komponen ProductDetail memiliki nama file ProductDetail.razor dan berada di folder Pages aplikasi.
  • Jalur file komponen untuk komponen yang dapat dirutekan cocok dengan URL mereka dalam kasus kebab‡ dengan tanda hubung yang muncul di antara kata-kata dalam templat rute komponen. Misalnya, komponen ProductDetail dengan template rute /product-detail (@page "/product-detail") diminta di browser di URL relatif /product-detail.

†Pascal case (camel case dengan huruf besar) adalah konvensi penamaan tanpa spasi dan tanda baca dan dengan huruf pertama dari setiap kata dikapitalisasi, termasuk kata pertama.
‡Kasus Kebab adalah konvensi penamaan tanpa spasi dan tanda baca yang menggunakan huruf kecil dan tanda hubung antar kata.

Komponen adalah kelas C# biasa dan dapat ditempatkan di mana saja dalam suatu proyek. Komponen yang menghasilkan halaman web biasanya berada di folder Pages. Komponen non-halaman sering ditempatkan di folder Shared atau folder kustom yang ditambahkan ke proyek.

Biasanya, namespace layanan komponen berasal dari namespace layanan akar aplikasi dan lokasi komponen (folder) di dalam aplikasi. Jika namespace layanan akar aplikasi adalah BlazorSample dan komponen Counter berada di folder Pages:

  • Namespace layanan komponen Counter adalah BlazorSample.Pages.
  • Nama jenis komponen yang sepenuhnya memenuhi syarat adalah BlazorSample.Pages.Counter.

Untuk folder kustom yang menyimpan komponen, tambahkan arahan @using ke komponen induk atau ke file _Imports.razor aplikasi. Contoh berikut membuat komponen dalam folder AdminComponents tersedia:

@using BlazorSample.AdminComponents

Catatan

Arahan @using dalam file _Imports.razor hanya diterapkan pada file Razor (.razor), bukan file C# (.cs).

Pernyataan alias using didukung. Dalam contoh berikut, kelas GridRendering publik WeatherForecast komponen tersedia seperti WeatherForecast di komponen di tempat lain di aplikasi:

@using WeatherForecast = Pages.GridRendering.WeatherForecast

Komponen juga dapat direferensikan menggunakan nama yang sepenuhnya memenuhi syarat, yang tidak memerlukan arahan @using. Contoh berikut secara langsung merujuk komponen ProductDetail di folder Components aplikasi:

<BlazorSample.Components.ProductDetail />

Namespace layanan komponen yang dibuat dengan Razor didasarkan pada hal berikut (dalam urutan prioritas):

  • Arahan @namespace di markup file Razor (misalnya, @namespace BlazorSample.CustomNamespace).
  • RootNamespace proyek dalam file proyek (misalnya, <RootNamespace>BlazorSample</RootNamespace>).
  • Namespace layanan proyek dan jalur dari akar proyek ke komponen. Misalnya, kerangka kerja diselesaikan {PROJECT NAMESPACE}/Pages/Index.razor dengan namespace BlazorSample proyek ke namespace BlazorSample.Pages layanan untuk Index komponen. {PROJECT NAMESPACE} adalah namespace proyek. Komponen mengikuti aturan pengikatan nama C#. Index Untuk komponen dalam contoh ini, komponen dalam cakupan adalah semua komponen:
    • Dalam folder yang sama, Pages.
    • Komponen di akar proyek yang tidak secara eksplisit menentukan namespace layanan yang berbeda.

Berikut ini tidak didukung:

  • Kualifikasi global::.
  • Nama yang memenuhi sebagian syarat. Misalnya, Anda tidak dapat menambahkan @using BlazorSample ke komponen lalu merujuk komponen NavMenu di folder Shared aplikasi (Shared/NavMenu.razor) dengan <Shared.NavMenu></Shared.NavMenu>.

Dukungan kelas parsial

Komponen dibuat sebagai kelas parsial C# dan dibuat menggunakan salah satu pendekatan berikut:

  • Satu file berisi kode C# yang ditentukan dalam satu atau beberapa blok @code, markup HTML, dan markup Razor. Template proyek Blazor menentukan komponennya menggunakan pendekatan file tunggal ini.
  • HTML dan markup Razor ditempatkan dalam file Razor (.razor). Kode C# ditempatkan dalam file di belakang kode yang didefinisikan sebagai kelas parsial (.cs).

Catatan

Lembar gaya komponen yang mendefinisikan gaya khusus komponen adalah file terpisah (.css). Isolasi CSS Blazor dijelaskan nanti di isolasi CSS Blazor ASP.NET Core.

Contoh berikut menunjukkan komponen Counter default dengan blok @code dalam aplikasi yang dihasilkan dari template proyek Blazor. Markup dan kode C# berada dalam file yang sama. Ini adalah pendekatan yang paling umum digunakan dalam penulisan komponen.

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

Komponen berikut Counter membagi HTML presentasi dan Razor markup dari kode C# menggunakan file code-behind dengan kelas parsial. Memisahkan markup dari kode C# disukai oleh beberapa organisasi dan pengembang untuk mengatur kode komponen mereka agar sesuai dengan cara kerja mereka. Misalnya, pakar UI organisasi dapat mengerjakan lapisan presentasi secara independen dari pengembang lain yang mengerjakan logika C# komponen. Pendekatan ini juga berguna saat bekerja dengan kode yang dihasilkan secara otomatis atau generator sumber. Untuk informasi selengkapnya, lihat Kelas dan Metode Parsial (Panduan Pemrograman C#).

CounterPartialClass.razor:

@page "/counter-partial-class"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@page "/counter-partial-class"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

CounterPartialClass.razor.cs:

namespace BlazorSample.Components.Pages;

public partial class CounterPartialClass
{
    private int currentCount = 0;

    private void IncrementCount() => currentCount++;
}
namespace BlazorSample.Components.Pages;

public partial class CounterPartialClass
{
    private int currentCount = 0;

    private void IncrementCount() => currentCount++;
}
namespace BlazorSample.Pages;

public partial class CounterPartialClass
{
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}
namespace BlazorSample.Pages
{
    public partial class CounterPartialClass
    {
        private int currentCount = 0;

        private void IncrementCount()
        {
            currentCount++;
        }
    }
}

Arahan @using dalam file _Imports.razor hanya diterapkan pada file Razor (.razor), bukan file C# (.cs). Tambahkan namespace layanan ke file kelas parsial sesuai kebutuhan.

Namespace layanan umum yang digunakan oleh komponen:

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;

Namespace layanan umum juga mencakup namespace layanan aplikasi dan namespace layanan yang sesuai dengan folder Components aplikasi:

using BlazorSample;
using BlazorSample.Components;

Folder tambahan juga dapat disertakan, seperti Layout folder:

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;

Namespace layanan umum juga mencakup namespace layanan aplikasi dan namespace layanan yang sesuai dengan folder Shared aplikasi:

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;

Namespace layanan umum juga mencakup namespace layanan aplikasi dan namespace layanan yang sesuai dengan folder Shared aplikasi:

using BlazorSample;
using BlazorSample.Shared;

Menentukan kelas dasar

Arahan @inherits digunakan untuk menentukan kelas dasar untuk suatu komponen. Tidak seperti menggunakan kelas parsial, yang hanya membagi markup dari logika C#, menggunakan kelas dasar memungkinkan Anda untuk mewarisi kode C# untuk digunakan di seluruh grup komponen yang berbagi properti dan metode kelas dasar. Menggunakan kelas dasar mengurangi redundansi kode di aplikasi dan berguna saat menyediakan kode dasar dari pustaka kelas ke beberapa aplikasi. Untuk informasi selengkapnya, lihat Warisan di C# dan .NET.

Dalam contoh berikut, BlazorRocksBase1 kelas dasar berasal dari 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!";
}

Perutean

Perutean di Blazor dicapai dengan menyediakan template rute ke setiap komponen yang dapat diakses di aplikasi dengan arahan @page. Saat file Razor dengan arahan @page dikompilasi, kelas yang dihasilkan diberi RouteAttribute yang menentukan template rute. Pada runtime bahasa umum, router mencari kelas komponen dengan RouteAttribute dan merender komponen mana pun yang memiliki template rute yang cocok dengan URL yang diminta.

Komponen berikut HelloWorld menggunakan templat /hello-worldrute , dan halaman web yang dirender untuk komponen tercapai di URL /hello-worldrelatif .

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>

Komponen sebelumnya dimuat di browser pada /hello-world terlepas dari apakah Anda menambahkan komponen ke navigasi antarmuka pengguna aplikasi atau tidak. Secara opsional, komponen dapat ditambahkan ke komponen NavMenu sehingga tautan ke komponen muncul di navigasi berbasis UI aplikasi.

Untuk komponen sebelumnya HelloWorld , Anda dapat menambahkan NavLink komponen ke NavMenu komponen. Untuk informasi lebih lanjut, termasuk deskripsi komponen NavLink dan NavMenu, lihat perutean dan navigasi Blazor ASP.NET Core.

Markup

Antarmuka pengguna komponen ditentukan menggunakan sintaks Razor, yang terdiri dari markup Razor, C#, dan HTML. Saat aplikasi dikompilasi, markup HTML dan logika perenderan C# diubah menjadi kelas komponen. Nama kelas yang dihasilkan cocok dengan nama file.

Anggota kelas komponen didefinisikan dalam satu atau lebih blok @code. Di blok @code, status komponen ditentukan dan diproses dengan C#:

  • Penginisialisasi properti dan bidang.
  • Nilai parameter dari argumen yang diteruskan oleh komponen induk dan parameter rute.
  • Metode untuk penanganan aktivitas pengguna, peristiwa siklus hidup, dan logika komponen kustom.

Anggota komponen digunakan dalam merender logika menggunakan ekspresi C# yang dimulai dengan simbol @. Misalnya, bidang C# dirender dengan awalan @ pada nama bidang. Komponen Markup berikut mengevaluasi dan merender:

  • headingFontStyle untuk nilai properti CSS font-style dari elemen judul.
  • headingText untuk konten elemen judul.

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

Catatan

Contoh di seluruh dokumentasi Blazor menentukan pengubah akses private untuk anggota privat. Anggota privat dicakupkan ke kelas komponen. Namun, C# mengasumsikan pengubah akses private ketika tidak ada pengubah akses, jadi secara eksplisit menandai anggota sebagai "private" dalam kode Anda sendiri sifatnya opsional. Untuk informasi lebih lanjut tentang pengubah akses, lihat Pengubah Akses (Panduan Pemrograman C#).

Blazor Kerangka kerja memproses komponen secara internal sebagai pohon render, yang merupakan kombinasi dari DOM komponen dan Model Objek Lembar Gaya Kaskading (CSSOM). Setelah komponen awalnya dirender, pohon render komponen dibuat ulang sebagai respons terhadap peristiwa. Blazor membandingkan pohon render baru dengan pohon render sebelumnya dan menerapkan modifikasi apa pun ke DOM browser untuk ditampilkan. Untuk informasi lebih lanjut, lihat perenderan komponen Razor ASP.NET Core.

Sintaks Razor untuk struktur kontrol C#, arahan, dan atribut arahan adalah huruf kecil (misalnya: @if, @code, @bind). Nama properti adalah huruf besar (misalnya: @Body untuk LayoutComponentBase.Body).

Metode asinkron (async) tidak mendukung pengembalian void

Kerangka kerja Blazor tidak melacak metode asinkron yang mengembalikan void (async). Akibatnya, pengecualian tidak ditangkap jika void dikembalikan. Selalu kembalikan Task dari metode asinkron.

Komponen yang disarangkan

Komponen dapat menyertakan komponen lain dengan mendeklarasikannya menggunakan sintaks HTML. Markup untuk menggunakan komponen terlihat seperti tag HTML di mana nama tag adalah jenis komponennya.

Perhatikan komponen Heading berikut, yang dapat digunakan oleh komponen lain untuk menampilkan judul.

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

Markup berikut dalam komponen HeadingExample merender komponen Heading sebelumnya di lokasi munculnya tag <Heading />.

HeadingExample.razor:

@page "/heading-example"

<PageTitle>Heading</PageTitle>

<h1>Heading Example</h1>

<Heading />
@page "/heading-example"

<PageTitle>Heading</PageTitle>

<h1>Heading Example</h1>

<Heading />
@page "/heading-example"

<Heading />
@page "/heading-example"

<Heading />
@page "/heading-example"

<Heading />
@page "/heading-example"

<Heading />

Jika komponen berisi elemen HTML dengan huruf pertama yang ditulis dalam huruf besar, yang tidak cocok dengan nama komponen dalam namespace layanan yang sama, akan muncul peringatan yang menunjukkan bahwa elemen tersebut memiliki nama yang tidak terduga. Menambahkan arahan @using untuk namespace layanan komponen membuat komponen tersedia, yang akan menyelesaikan peringatan tersebut. Untuk informasi selengkapnya, lihat bagian Nama komponen , nama kelas, dan namespace layanan.

Contoh komponen Heading yang ditampilkan di bagian ini tidak memiliki arahan @page, sehingga komponen Heading tidak dapat diakses secara langsung oleh pengguna melalui permintaan langsung di browser. Namun, komponen apa pun dengan arahan @page dapat disarangkan di komponen lain. Jika komponen Heading dapat diakses secara langsung dengan menyertakan @page "/heading" di bagian atas file Razor-nya, maka komponen tersebut akan dirender untuk permintaan browser di /heading dan /heading-example.

Parameter komponen

Parameter komponen meneruskan data ke komponen dan ditentukan menggunakan properti C# publik pada kelas komponen dengan atribut [Parameter]. Dalam contoh berikut, jenis referensi bawaan (System.String) dan jenis referensi yang ditentukan pengguna (PanelBody) diteruskan sebagai parameter komponen.

PanelBody.cs:

namespace BlazorSample;

public class PanelBody
{
    public string? Text { get; set; }
    public string? Style { get; set; }
}
namespace BlazorSample;

public class PanelBody
{
    public string? Text { get; set; }
    public string? Style { get; set; }
}
public class PanelBody
{
    public string? Text { get; set; }
    public string? Style { get; set; }
}
public class PanelBody
{
    public string? Text { get; set; }
    public string? Style { get; set; }
}
public class PanelBody
{
    public string Text { get; set; }
    public string Style { get; set; }
}
public class PanelBody
{
    public string Text { get; set; }
    public string Style { get; set; }
}

ParameterChild.razor:

<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">@Title</div>
    <div class="card-body" style="font-style:@Body.Style">
        @Body.Text
    </div>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = "Set By Child";

    [Parameter]
    public PanelBody Body { get; set; } =
        new()
        {
            Text = "Card content set by child.",
            Style = "normal"
        };
}
<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">@Title</div>
    <div class="card-body" style="font-style:@Body.Style">
        @Body.Text
    </div>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = "Set By Child";

    [Parameter]
    public PanelBody Body { get; set; } =
        new()
        {
            Text = "Card content set by child.",
            Style = "normal"
        };
}
<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">@Title</div>
    <div class="card-body" style="font-style:@Body.Style">
        @Body.Text
    </div>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = "Set By Child";

    [Parameter]
    public PanelBody Body { get; set; } =
        new()
        {
            Text = "Set by child.",
            Style = "normal"
        };
}
<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">@Title</div>
    <div class="card-body" style="font-style:@Body.Style">
        @Body.Text
    </div>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = "Set By Child";

    [Parameter]
    public PanelBody Body { get; set; } =
        new()
        {
            Text = "Set by child.",
            Style = "normal"
        };
}
<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">@Title</div>
    <div class="card-body" style="font-style:@Body.Style">
        @Body.Text
    </div>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = "Set By Child";

    [Parameter]
    public PanelBody Body { get; set; } =
        new()
        {
            Text = "Set by child.",
            Style = "normal"
        };
}
<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">@Title</div>
    <div class="card-body" style="font-style:@Body.Style">
        @Body.Text
    </div>
</div>

@code {
    [Parameter]
    public string Title { get; set; } = "Set By Child";

    [Parameter]
    public PanelBody Body { get; set; } =
        new PanelBody()
        {
            Text = "Set by child.",
            Style = "normal"
        };
}

Peringatan

Memberikan nilai awal untuk parameter komponen didukung, tetapi jangan membuat komponen yang menulis ke parameternya sendiri setelah komponen dirender untuk pertama kalinya. Untuk informasi selengkapnya, lihat Menghindari penimpaan parameter di ASP.NET Core Blazor.

Parameter komponen Title dan Body dari komponen ParameterChild ditetapkan oleh argumen dalam tag HTML yang merender instans komponen. Komponen ParameterParent berikut merender dua komponen ParameterChild:

  • Komponen ParameterChild pertama dirender tanpa memberikan argumen parameter.
  • Komponen ParameterChild kedua menerima nilai untuk Title dan Body dari komponen ParameterParent, yang menggunakan ekspresi C# eksplisit untuk mengatur nilai properti PanelBody.

Parameter1.razor:

@page "/parameter-1"

<PageTitle>Parameter 1</PageTitle>

<h1>Parameter Example 1</h1>

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

<ParameterChild />

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

<ParameterChild Title="Set by Parent" 
    Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />

Parameter1.razor:

@page "/parameter-1"

<PageTitle>Parameter 1</PageTitle>

<h1>Parameter Example 1</h1>

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

<ParameterChild />

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

<ParameterChild Title="Set by Parent" 
    Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />

ParameterParent.razor:

@page "/parameter-parent"

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

<ParameterChild />

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

<ParameterChild Title="Set by Parent"
                Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />

ParameterParent.razor:

@page "/parameter-parent"

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

<ParameterChild />

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

<ParameterChild Title="Set by Parent"
                Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />

ParameterParent.razor:

@page "/parameter-parent"

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

<ParameterChild />

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

<ParameterChild Title="Set by Parent"
                Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />

ParameterParent.razor:

@page "/parameter-parent"

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

<ParameterChild />

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

<ParameterChild Title="Set by Parent"
                Body="@(new PanelBody() { Text = "Set by parent.", Style = "italic" })" />

Markup HTML yang dirender berikut dari komponen ParameterParent menunjukkan nilai default komponen ParameterChild jika komponen ParameterParent tidak menyediakan nilai parameter komponen. Saat komponen ParameterParent memberikan nilai parameter komponen, komponen tersebut menggantikan nilai default komponen ParameterChild.

Catatan

Untuk lebih jelasnya, kelas gaya CSS yang dirender tidak ditampilkan dalam markup HTML yang dirender berikut.

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

<div>
    <div>Set By Child</div>
    <div>Set by child.</div>
</div>

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

<div>
    <div>Set by Parent</div>
    <div>Set by parent.</div>
</div>

Tetapkan bidang C#, properti, atau hasil metode ke parameter komponen sebagai nilai atribut HTML. Nilai atribut biasanya dapat berupa ekspresi C# apa pun yang cocok dengan jenis parameter. Nilai atribut dapat secara opsional mengarah dengan simbol yang Razor dipesan@, tetapi tidak diperlukan.

Jika parameter komponen adalah jenis string, maka nilai atribut malah diperlakukan sebagai string C# literal. Jika Anda ingin menentukan ekspresi C#, maka gunakan awalan @ .

Komponen ParameterParent2 berikut menampilkan empat instans komponen ParameterChild sebelumnya dan mengatur nilai parameter Title ke:

  • Nilai bidang title.
  • Hasil dari metode C# GetTitle.
  • Tanggal lokal saat ini dalam format panjang dengan ToLongDateString, yang menggunakan ekspresi C# implisit.
  • Properti Title objek panelData.

Kutipan di sekitar nilai atribut parameter bersifat opsional dalam banyak kasus sesuai spesifikasi HTML5. Misalnya, Value=this didukung, alih-alih Value="this". Namun, sebaiknya gunakan tanda kutip karena lebih mudah diingat dan diadopsi secara luas di seluruh teknologi berbasis web.

Sepanjang dokumentasi, contoh kode:

  • Selalu menggunakan kutipan. Contoh: Value="this".
  • Jangan gunakan awalan @ dengan nonliteral kecuali diperlukan. Contoh: Count="ct", di mana ct adalah variabel berjenis angka. Count="@ct" adalah pendekatan gaya yang valid, tetapi dokumentasi dan contoh tidak mengadopsi konvensi.
  • Selalu hindari @ untuk harfiah, di luar Razor ekspresi. Contoh: IsFixed="true". Ini termasuk kata kunci (misalnya, this) dan null, tetapi Anda dapat memilih untuk menggunakannya jika Anda mau. Misalnya, IsFixed="@true" tidak umum tetapi didukung.

Parameter2.razor:

@page "/parameter-2"

<PageTitle>Parameter 2</PageTitle>

<h1>Parameter Example 2</h1>

<ParameterChild Title="@title" />

<ParameterChild Title="@GetTitle()" />

<ParameterChild Title="@DateTime.Now.ToLongDateString()" />

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

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

    private string GetTitle() => "From Parent method";

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

Parameter2.razor:

@page "/parameter-2"

<PageTitle>Parameter 2</PageTitle>

<h1>Parameter Example 2</h1>

<ParameterChild Title="@title" />

<ParameterChild Title="@GetTitle()" />

<ParameterChild Title="@DateTime.Now.ToLongDateString()" />

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

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

    private string GetTitle() => "From Parent method";

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

ParameterParent2.razor:

@page "/parameter-parent-2"

<ParameterChild Title="@title" />

<ParameterChild Title="@GetTitle()" />

<ParameterChild Title="@DateTime.Now.ToLongDateString()" />

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

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

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

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

ParameterParent2.razor:

@page "/parameter-parent-2"

<ParameterChild Title="@title" />

<ParameterChild Title="@GetTitle()" />

<ParameterChild Title="@DateTime.Now.ToLongDateString()" />

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

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

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

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

ParameterParent2.razor:

@page "/parameter-parent-2"

<ParameterChild Title="@title" />

<ParameterChild Title="@GetTitle()" />

<ParameterChild Title="@DateTime.Now.ToLongDateString()" />

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

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

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

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

Catatan

Saat menetapkan anggota C# ke parameter komponen, jangan awali atribut HTML parameter dengan @.

Benar (Title adalah parameter string, Count adalah parameter berjenis angka):

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

Salah:

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

Tidak seperti di halaman Razor (.cshtml), Blazor tidak dapat melakukan pekerjaan asinkron dalam ekspresi Razor saat merender komponen. Ini karena Blazor dirancang untuk merender antarmuka pengguna interaktif. Dalam antarmuka pengguna interaktif, layar harus selalu menampilkan sesuatu, jadi tidak masuk akal untuk memblokir aliran perenderan. Sebagai gantinya, pekerjaan asinkron dilakukan selama salah satu peristiwa siklus hidup asinkron. Setelah setiap peristiwa siklus hidup asinkron, komponen dapat merender lagi. Sintaks Razor berikut tidak didukung:

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

Kode dalam contoh sebelumnya menghasilkan kesalahan kompilator saat aplikasi dibangun:

Operator 'await' hanya dapat digunakan dalam metode asinkron. Pertimbangkan untuk menandai metode ini dengan pengubah 'async' dan mengubah jenis pengembaliannya menjadi 'Task'.

Untuk mendapatkan nilai parameter Title dalam contoh sebelumnya secara asinkron, komponen dapat menggunakan peristiwa siklus hidup OnInitializedAsync, seperti yang ditunjukkan contoh berikut:

<ParameterChild Title="@title" />

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

Untuk informasi lebih lanjut, lihat siklus hidup komponen Razor ASP.NET Core.

Penggunaan ekspresi Razor eksplisit untuk menggabungkan teks dengan hasil ekspresi untuk penetapan ke parameter tidak didukung. Contoh berikut berupaya menggabungkan teks "Set by " dengan nilai properti objek. Meskipun sintaks ini didukung di halaman Razor (.cshtml), sintaks ini tidak valid untuk penetapan parameter Title turunan dalam suatu komponen. Sintaks Razor berikut tidak didukung:

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

Kode dalam contoh sebelumnya menghasilkan kesalahan kompilator saat aplikasi dibangun:

Atribut komponen tidak mendukung konten yang kompleks (campuran C# dan markup).

Untuk mendukung penetapan nilai yang tersusun, gunakan metode, bidang, atau properti. Contoh berikut melakukan penggabungan "Set by " dan nilai properti objek dalam metode C# 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";
    }
}

Untuk informasi lebih lanjut, lihat Referensi sintaks Razor untuk ASP.NET Core.

Peringatan

Memberikan nilai awal untuk parameter komponen didukung, tetapi jangan membuat komponen yang menulis ke parameternya sendiri setelah komponen dirender untuk pertama kalinya. Untuk informasi selengkapnya, lihat Menghindari penimpaan parameter di ASP.NET Core Blazor.

Parameter komponen harus dideklarasikan sebagai auto-properties, artinya parameter tersebut tidak boleh berisi logika kustom di pengakses get atau set-nya. Misalnya, properti StartData berikut adalah properti otomatis:

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

Jangan tempatkan logika kustom di pengakses get atau set karena parameter komponen murni dimaksudkan untuk digunakan sebagai saluran bagi komponen induk untuk mengalirkan informasi ke komponen turunan. Jika pengakses set dari properti komponen turunan berisi logika yang menyebabkan perenderan ulang komponen induk, makan akan menyebabkan perulangan perenderan tak terbatas.

Untuk mengubah nilai parameter yang diterima:

  • Biarkan properti parameter sebagai properti otomatis untuk mewakili data mentah yang disediakan.
  • Buat properti atau metode yang berbeda untuk menyediakan data yang diubah berdasarkan properti parameter.

Timpa OnParametersSetAsync untuk mengubah parameter yang diterima setiap kali data baru diterima.

Penulisan nilai awal ke parameter komponen didukung karena penetapan nilai awal tidak mengganggu perenderan komponen otomatis Blazor. Penetapan DateTime lokal saat ini dengan DateTime.Now ke StartData berikut adalah sintaks yang valid dalam sebuah komponen:

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

Setelah penetapan awal DateTime.Now, jangan menetapkan nilai ke StartData dalam kode pengembang. Untuk informasi selengkapnya, lihat Menghindari penimpaan parameter di ASP.NET Core Blazor.

Terapkan atribut [EditorRequired] untuk menentukan parameter komponen yang diperlukan. Jika nilai parameter tidak diberikan, editor atau alat build dapat menampilkan peringatan kepada pengguna. Atribut ini hanya valid pada properti yang juga ditandai dengan atribut [Parameter]. EditorRequiredAttribute diberlakukan pada waktu desain dan saat aplikasi dibangun. Atribut tidak diberlakukan pada runtime bahasa umum, dan tidak menjamin nilai parameter non-null.

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

Daftar atribut satu baris juga didukung:

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

Jangan gunakan pengubah required atau init aksesor pada properti parameter komponen. Komponen biasanya dibuat dan ditetapkan nilai parameter menggunakan pantulan, yang melewati jaminan yang init dan required dirancang untuk dibuat. Sebagai gantinya [EditorRequired] , gunakan atribut untuk menentukan parameter komponen yang diperlukan.

Jangan gunakan init aksesor pada properti parameter komponen karena mengatur nilai parameter komponen dengan ParameterView.SetParameterProperties menggunakan pantulan, yang melewati pembatasan setter init-only. [EditorRequired] Gunakan atribut untuk menentukan parameter komponen yang diperlukan.

Jangan gunakan init aksesor pada properti parameter komponen karena mengatur nilai parameter komponen dengan ParameterView.SetParameterProperties menggunakan pantulan, yang melewati pembatasan setter init-only.

Tuples (dokumentasi API) didukung untuk parameter komponen dan jenis RenderFragment. Contoh parameter komponen berikut meneruskan tiga nilai dalam Tuple:

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

Tuple bernama didukung, seperti yang terlihat dalam contoh berikut:

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 (dokumentasi API) didukung untuk parameter komponen dan jenis RenderFragment. Contoh parameter komponen berikut meneruskan tiga nilai dalam Tuple:

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

Tuple bernama didukung, seperti yang terlihat dalam contoh berikut:

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 (dokumentasi API) didukung untuk parameter komponen dan jenis RenderFragment. Contoh parameter komponen berikut meneruskan tiga nilai dalam Tuple:

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

Tuple bernama didukung, seperti yang terlihat dalam contoh berikut:

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)

Parameter rute

Komponen dapat menentukan parameter rute dalam template rute dari arahan @page. Router Blazor menggunakan parameter rute untuk mengisi parameter komponen yang sesuai.

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

Untuk informasi selengkapnya, lihat bagian Parameter rute dari perutean dan navigasi inti Blazor ASP.NET. Parameter rute opsional juga didukung dan dibahas di bagian yang sama. Untuk informasi tentang parameter rute catch-all ({*pageRoute}), yang mengambil jalur di beberapa batas folder, lihat bagian Parameter rute Catch-all dari perutean dan navigasi Inti Blazor ASP.NET.

Untuk informasi selengkapnya, lihat bagian Parameter rute dari perutean dan navigasi inti Blazor ASP.NET. Parameter rute opsional tidak didukung, jadi diperlukan dua @page arahan (lihat bagian Parameter rute untuk informasi selengkapnya). Untuk informasi tentang parameter rute catch-all ({*pageRoute}), yang mengambil jalur di beberapa batas folder, lihat bagian Parameter rute Catch-all dari perutean dan navigasi Inti Blazor ASP.NET.

Peringatan

Dengan kompresi, yang diaktifkan secara default, hindari membuat komponen sisi server interaktif yang aman (diautentikasi/diotorisasi) yang merender data dari sumber yang tidak tepercaya. Sumber yang tidak tepercaya termasuk parameter rute, string kueri, data dari JS interop, dan sumber data lain yang dapat dikontrol pengguna pihak ketiga (database, layanan eksternal). Untuk informasi selengkapnya, lihat panduan inti BlazorSignalR ASP.NET dan panduan mitigasi ancaman untuk penyajian sisi server interaktif ASP.NET CoreBlazor.

Fragmen render konten turunan

Komponen dapat mengatur isi dari komponen lain. Komponen penetapan menyediakan konten antara tag pembuka dan penutup komponen turunan.

Dalam contoh berikut, komponen RenderFragmentChild memiliki parameter komponen ChildContent yang mewakili segmen antarmuka pengguna untuk dirender sebagai RenderFragment. Posisi ChildContent dalam markup Razor komponen adalah tempat konten dirender dalam output HTML akhir.

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

Penting

Properti yang menerima konten RenderFragment harus diberi nama ChildContent berdasarkan konvensi.

Panggilan balik peristiwa tidak didukung untuk RenderFragment.

Komponen berikut menyediakan konten untuk merender RenderFragmentChild dengan menempatkan konten di dalam tag pembukaan dan penutup komponen anak.

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>

Fragmen render digunakan untuk merender konten turunan di seluruh aplikasi Blazor dan dijelaskan dengan contoh di artikel dan bagian artikel berikut:

Catatan

Komponen Razor bawaan kerangka kerja Blazor menggunakan konvensi parameter komponen ChildContent yang sama untuk mengatur kontennya. Anda dapat melihat komponen yang mengatur konten turunan dengan mencari ChildContent nama properti parameter komponen di dokumentasi API (memfilter API dengan istilah pencarian "ChildContent").

Merender fragmen untuk logika perenderan yang dapat digunakan kembali

Anda dapat memfaktorkan komponen turunan murni sebagai cara untuk menggunakan kembali logika perenderan. Di blok @code komponen mana pun, tentukan RenderFragment dan render fragmen dari lokasi mana pun sebanyak yang diperlukan:

@RenderWelcomeInfo

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

@RenderWelcomeInfo

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

Untuk informasi lebih lanjut, lihat Menggunakan kembali logika perenderan.

Variabel perulangan dengan parameter komponen dan konten turunan

Komponen penyajian di dalam for perulangan memerlukan variabel indeks lokal jika variabel perulangan yang bertambah banyak digunakan oleh parameter komponen atau RenderFragment konten turunan.

Pertimbangkan komponen berikut RenderFragmentChild2 yang memiliki parameter komponen (Id) dan fragmen render untuk menampilkan konten anak (ChildContent).

RenderFragmentChild2.razor:

<div class="card w-25" style="margin-bottom:15px">
    <div class="card-header font-weight-bold">Child content (@Id)</div>
    <div class="card-body">@ChildContent</div>
</div>

@code {
    [Parameter]
    public string? Id { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Saat merender RenderFragmentChild2 komponen dalam komponen induk, gunakan variabel indeks lokal (ct dalam contoh berikut) alih-alih variabel perulangan (c) saat menetapkan nilai parameter komponen dan menyediakan konten komponen anak:

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

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

Atau, gunakan perulangan foreach dengan Enumerable.Range alih-alih perulangan for :

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

Mengambil referensi ke komponen

Referensi komponen menyediakan cara untuk mereferensikan instans komponen untuk mengeluarkan perintah. Untuk mengambil referensi komponen:

  • Tambahkan atribut @ref ke komponen turunan.
  • Tentukan bidang dengan jenis yang sama dengan komponen turunan.

Saat komponen dirender, bidang diisi dengan instans komponen. Anda kemudian dapat memanggil metode .NET pada instans.

Pertimbangkan komponen ReferenceChild berikut yang mencatat pesan saat ChildMethod-nya dipanggil.

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

Referensi komponen hanya diisi setelah komponen dirender dan outputnya menyertakan elemen ReferenceChild. Sampai komponen dirender, tidak ada referensi apa pun. Jangan mencoba memanggil metode komponen yang direferensikan ke penanganan aktivitas secara langsung (misalnya, @onclick="childComponent!.ChildMethod(5)") karena variabel referensi mungkin tidak ditetapkan pada saat peristiwa klik ditetapkan.

Untuk memanipulasi referensi komponen setelah komponen selesai dirender, gunakan metode OnAfterRender atau OnAfterRenderAsync.

Contoh berikut menggunakan komponen sebelumnya ReferenceChild .

ReferenceParent.razor:

@page "/reference-parent"

<div>
    <button @onclick="@(() => childComponent1!.ChildMethod(5))">
        Call <code>ReferenceChild.ChildMethod</code> (first instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent1" />
</div>

<div>
    <button @onclick="CallChildMethod">
        Call <code>ReferenceChild.ChildMethod</code> (second instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent2" />
</div>

@code {
    private ReferenceChild? childComponent1;
    private ReferenceChild? childComponent2;

    private void CallChildMethod() => childComponent2!.ChildMethod(5);
}
@page "/reference-parent"

<div>
    <button @onclick="@(() => childComponent1!.ChildMethod(5))">
        Call <code>ReferenceChild.ChildMethod</code> (first instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent1" />
</div>

<div>
    <button @onclick="CallChildMethod">
        Call <code>ReferenceChild.ChildMethod</code> (second instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent2" />
</div>

@code {
    private ReferenceChild? childComponent1;
    private ReferenceChild? childComponent2;

    private void CallChildMethod() => childComponent2!.ChildMethod(5);
}
@page "/reference-parent"

<div>
    <button @onclick="@(() => childComponent1!.ChildMethod(5))">
        Call <code>ReferenceChild.ChildMethod</code> (first instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent1" />
</div>

<div>
    <button @onclick="CallChildMethod">
        Call <code>ReferenceChild.ChildMethod</code> (second instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent2" />
</div>

@code {
    private ReferenceChild? childComponent1;
    private ReferenceChild? childComponent2;

    private void CallChildMethod()
    {
        childComponent2!.ChildMethod(5);
    }
}
@page "/reference-parent"

<div>
    <button @onclick="@(() => childComponent1!.ChildMethod(5))">
        Call <code>ReferenceChild.ChildMethod</code> (first instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent1" />
</div>

<div>
    <button @onclick="CallChildMethod">
        Call <code>ReferenceChild.ChildMethod</code> (second instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent2" />
</div>

@code {
    private ReferenceChild? childComponent1;
    private ReferenceChild? childComponent2;

    private void CallChildMethod()
    {
        childComponent2!.ChildMethod(5);
    }
}
@page "/reference-parent"

<div>
    <button @onclick="@(() => childComponent1!.ChildMethod(5))">
        Call <code>ReferenceChild.ChildMethod</code> (first instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent1" />
</div>

<div>
    <button @onclick="CallChildMethod">
        Call <code>ReferenceChild.ChildMethod</code> (second instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent2" />
</div>

@code {
    private ReferenceChild childComponent1;
    private ReferenceChild childComponent2;

    private void CallChildMethod()
    {
        childComponent2!.ChildMethod(5);
    }
}
@page "/reference-parent"

<div>
    <button @onclick="@(() => childComponent1!.ChildMethod(5))">
        Call <code>ReferenceChild.ChildMethod</code> (first instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent1" />
</div>

<div>
    <button @onclick="CallChildMethod">
        Call <code>ReferenceChild.ChildMethod</code> (second instance) 
        with an argument of 5
    </button>

    <ReferenceChild @ref="childComponent2" />
</div>

@code {
    private ReferenceChild childComponent1;
    private ReferenceChild childComponent2;

    private void CallChildMethod()
    {
        childComponent2!.ChildMethod(5);
    }
}

Meskipun pengambilan referensi komponen menggunakan sintaks yang mirip dengan pengambilan referensi elemen, pengambilan referensi komponen bukanlah fitur interop JavaScript. Referensi komponen tidak diteruskan ke kode JavaScript. Referensi komponen hanya digunakan dalam kode .NET.

Penting

Jangan menggunakan referensi komponen untuk mengubah status komponen turunan. Sebagai gantinya, gunakan parameter komponen deklaratif normal untuk meneruskan data ke komponen turunan. Penggunaan parameter komponen menyebabkan komponen turunan yang dirender ulang pada waktu yang tepat secara otomatis. Untuk informasi lebih lanjut, lihat bagian parameter komponen dan artikel pengikatan data Blazor ASP.NET Core.

Menerapkan atribut

Atribut dapat diterapkan ke komponen dengan arahan @attribute. Contoh berikut menerapkan atribut [Authorize] ke kelas komponen:

@page "/"
@attribute [Authorize]

Atribut elemen HTML bersyar dan properti DOM

Blazor mengadopsi perilaku umum berikut:

  • Untuk atribut HTML, Blazor atur atau hapus atribut secara kondisional berdasarkan nilai .NET. Jika nilai .NET adalah false atau null, atribut tidak diatur atau dihapus jika sebelumnya diatur.
  • Untuk properti DOM, seperti checked atau value, Blazor mengatur properti DOM berdasarkan nilai .NET. Jika nilai .NET adalah false atau null, properti DOM diatur ulang ke nilai default.

Atribut sintaks mana Razor yang sesuai dengan atribut HTML dan mana yang sesuai dengan properti DOM tetap tidak terdokumentasi karena ini adalah detail implementasi kerangka kerja yang mungkin berubah tanpa pemberitahuan.

Peringatan

Beberapa atribut HTML, seperti aria-pressed, harus memiliki nilai string "true" atau "false". Karena memerlukan nilai string dan bukan boolean, Anda harus menggunakan .NET string dan bukan bool untuk nilainya. Ini adalah persyaratan yang ditetapkan oleh API DOM browser.

HTML mentah

String biasanya dirender menggunakan node teks DOM, yang berarti bahwa markup apa pun yang dikandungnya akan diabaikan dan diperlakukan sebagai teks harfiah. Untuk merender HTML mentah, bungkus konten HTML dalam nilai MarkupString. Nilai diurai sebagai HTML atau SVG dan disisipkan ke dalam DOM.

Peringatan

Perenderan HTML mentah yang dibuat dari sumber yang tidak tepercaya merupakan risiko keamanan dan harus selalu dihindari.

Contoh berikut menunjukkan penggunaan jenis MarkupString untuk menambahkan blok konten HTML statis ke output komponen yang dirender.

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

Template Razor

Fragmen render dapat ditentukan menggunakan sintaks template Razor untuk menentukan cuplikan antarmuka pengguna. Template Razor menggunakan format berikut:

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

Contoh berikut mengilustrasikan cara menentukan nilai RenderFragment dan RenderFragment<TValue> serta merender template secara langsung dalam komponen. Render fragmen juga dapat diteruskan sebagai argumen ke komponen template.

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

Output yang dirender dari kode sebelumnya:

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

Aset statis

Blazor mengikuti konvensi aplikasi ASP.NET Core untuk aset statis. Aset statis terletak di folder web root (wwwroot) proyek atau folder di bawah folder wwwroot.

Gunakan jalur relatif dasar (/) guna merujuk ke akar web untuk aset statis. Dalam contoh berikut, logo.png secara fisik terletak di folder {PROJECT ROOT}/wwwroot/images. {PROJECT ROOT} adalah akar proyek aplikasi.

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

Komponen tidak mendukung notasi tilde-slash (~/).

Untuk informasi tentang mengatur jalur dasar aplikasi, lihat Menghosting dan menyebarkan Blazor ASP.NET Core.

Pembantu Tag tidak didukung di komponen

Tag Helpers tidak didukung dalam komponen. Untuk menyediakan fungsionalitas seperti Pembantu Tag di Blazor, buat komponen dengan fungsi yang sama seperti Pembantu Tag dan gunakan komponen sebagai gantinya.

Gambar Scalable Vector Graphics (SVG)

Karena Blazor merender HTML, gambar yang didukung browser, termasuk gambar Scalable Vector Graphics (SVG) (.svg), didukung melalui tag <img>:

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

Demikian pula, gambar SVG didukung dalam aturan CSS dari file lembar gaya (.css):

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

Blazor mendukung elemen <foreignObject> untuk menampilkan HTML arbitrer dalam SVG. Markup dapat mewakili HTML arbitrer, RenderFragment, atau komponen Razor.

Contoh berikut menunjukkan:

  • Tampilan string (@message).
  • Pengikatan dua arah dengan elemen <input> dan bidang value.
  • Komponen Robot.
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect x="0" y="0" rx="10" ry="10" width="200" height="200" stroke="black" 
        fill="none" />
    <foreignObject x="20" y="20" width="160" height="160">
        <p>@message</p>
    </foreignObject>
</svg>

<svg xmlns="http://www.w3.org/2000/svg">
    <foreignObject width="200" height="200">
        <label>
            Two-way binding:
            <input @bind="value" @bind:event="oninput" />
        </label>
    </foreignObject>
</svg>

<svg xmlns="http://www.w3.org/2000/svg">
    <foreignObject>
        <Robot />
    </foreignObject>
</svg>

@code {
    private string message = "Lorem ipsum dolor sit amet, consectetur adipiscing " +
        "elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";

    private string? value;
}

Perilaku perenderan spasi kosong

Kecuali direktif @preservewhitespace digunakan dengan nilai true, spasi kosong tambahan dihapus jika:

  • Di depan atau di belakang dalam elemen.
  • Di depan atau di belakang dalam parameter RenderFragment/RenderFragment<TValue> (misalnya, konten turunan diteruskan ke komponen lain).
  • Ini mendahului atau mengikuti blok kode C#, seperti @if atau @foreach.

Penghapusan spasi kosong dapat memengaruhi output yang dirender saat menggunakan aturan CSS, seperti white-space: pre. Untuk menonaktifkan pengoptimalan performa ini dan mempertahankan spasi kosong, lakukan salah satu tindakan berikut:

  • Tambahkan arahan @preservewhitespace true di bagian atas file Razor (.razor) untuk menerapkan preferensi ke komponen tertentu.
  • Tambahkan arahan @preservewhitespace true di dalam file _Imports.razor untuk menerapkan preferensi ke subdirektori atau ke seluruh proyek.

Dalam kebanyakan kasus, tidak ada tindakan yang diperlukan, karena aplikasi biasanya terus berperilaku normal (tetapi lebih cepat). Jika menghapus spasi kosong menyebabkan masalah perenderan untuk komponen tertentu, gunakan @preservewhitespace true dalam komponen tersebut untuk menonaktifkan pengoptimalan ini.

Spasi kosong dipertahankan dalam markup sumber komponen. Teks khusus spasi kosong dirender di DOM browser meskipun tidak ada efek visual.

Pertimbangkan markup komponen berikut:

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

Contoh sebelumnya merender spasi kosong yang tidak perlu berikut ini:

  • Di luar blok kode @foreach.
  • Di sekitar elemen <li>.
  • Di sekitar output @item.Text.

Daftar 100 item menghasilkan lebih dari 400 area spasi kosong. Tidak satu pun dari spasi kosong ekstra yang secara visual memengaruhi output yang dirender.

Saat merender HTML statis untuk komponen, spasi kosong di dalam tag tidak dipertahankan. Misalnya, lihat output yang dirender dari tag <img> berikut dalam file Razor komponen (.razor):

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

Spasi kosong tidak dipertahankan dari markup sebelumnya:

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

Komponen akar

Komponen akar Razor (komponen akar) adalah komponen pertama yang dimuat dari hierarki komponen apa pun yang dibuat oleh aplikasi.

Dalam aplikasi yang dibuat dari Blazor Web App templat proyek, App komponen (App.razor) ditentukan sebagai komponen akar default oleh parameter jenis yang dideklarasikan untuk panggilan ke MapRazorComponents<TRootComponent> dalam file sisi Program server. Contoh berikut menunjukkan penggunaan App komponen sebagai komponen akar, yang merupakan default untuk aplikasi yang dibuat dari Blazor templat proyek:

app.MapRazorComponents<App>();

Catatan

Membuat komponen akar interaktif, seperti App komponen, tidak didukung.

Dalam aplikasi yang dibuat dari Blazor Server templat proyek, App komponen (App.razor) ditentukan sebagai komponen akar default dalam Pages/_Host.cshtml menggunakan Bantuan Tag Komponen:

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

Dalam aplikasi yang dibuat dari Blazor WebAssembly templat proyek, App komponen (App.razor) ditentukan sebagai komponen akar default dalam Program file:

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

Dalam kode sebelumnya, pemilih CSS, #app, menunjukkan bahwa App komponen ditentukan untuk <div> masuk wwwroot/index.html dengan id dari app:

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

Aplikasi MVC dan Razor Pages juga dapat menggunakan Pembantu Tag Komponen untuk mendaftarkan komponen akar yang dirender Blazor WebAssembly secara statis:

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

Komponen yang dirender secara statis hanya dapat ditambahkan ke aplikasi. Mereka tidak dapat dihapus atau diperbarui setelahnya.

Untuk informasi selengkapnya, lihat sumber daya berikut: