ASP.NET Core Razor 元件
注意
這不是本文的最新版本。 如需目前的版本,請參閱 本文 的 .NET 7 版本。
本文說明如何在 Blazor 應用程式中建立和使用 Razor 元件,包括 Razor 語法、元件命名、命名空間和元件參數的指引。
Blazor應用程式是使用 元件來建置,非正式地稱為 Blazor 元件 或僅限 元件 。 Razor 元件是使用者介面 (UI) 的獨立部分,具有處理邏輯而能夠啟用動態行為。 元件可巢狀處理、重複使用、在專案之間共用,以及用於 MVC 和 Razor Pages 應用程式。
元件類別
元件會使用 C# 和 HTML 標記的組合,實作到副檔名為 .razor
的 Razor 元件檔案中。
根據預設, ComponentBase 是元件檔案所 Razor 描述之元件的基類。 ComponentBase 會實作元件的最低抽象概念,即 IComponent 介面。 ComponentBase 定義基本功能的元件屬性和方法,例如,處理一組內建元件生命週期事件。
ComponentBase
在參考來源 中 dotnet/aspnetcore
:參考來源包含內建生命週期事件的其他備註。 不過,請記住,元件功能的內部實作隨時可能隨時變更,而不通知。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
開發人員通常會從 Razor 元件檔案 ( .razor
) 建立 Razor 元件,或建立其元件的基礎 ComponentBase ,但也可以藉由實 IComponent 作 來建置元件。 實作的 IComponent 開發人員建置元件,可以透過開發人員必須建立和維護的事件和生命週期方法手動觸發轉譯,而不需要對轉譯採取低階控制。
Razor 語法
元件會使用 Razor 語法。 元件廣泛使用兩個 Razor 功能,分別是「指示詞」和「指示詞屬性」。 這兩個功能是會出現在 Razor 標記中、且前面加上 @
的保留關鍵字:
- 指示詞:會變更元件標記的剖析或運作方式。 例如,
@page
指示詞會指定具有路由範本的可路由元件,而且使用者只要透過瀏覽器在特定 URL 中提出要求即可直接連線。 - 指示詞屬性:會變更元件元素的剖析或運作方式。 例如,
<input>
元素的@bind
指示詞屬性會將資料繫結至元素的值。
本文和其他 Blazor 元件集文章會進一步說明元件中使用的指示詞和指示詞屬性。 如需 Razor 語法的一般資訊,請參閱 ASP.NET Core 的 Razor 語法參考。
元件名稱、類別名稱和命名空間
元件的名稱必須以大寫字元開頭:
支援:ProductDetail.razor
支援:productDetail.razor
Blazor 文件中使用的通用 Blazor 命名慣例包括:
- 檔案路徑和檔案名會使用 Pascal 大小寫†並顯示在顯示程式碼範例之前。 如果路徑存在,表示一般資料夾位置。 例如,
Components/Pages/ProductDetail.razor
表示ProductDetail
元件具有 的ProductDetail.razor
檔案名,且位於Pages
應用程式資料夾的 資料夾中Components
。 - 可路由元件的元件檔案路徑會比對基底案例中的 URL} ,而元件路由範本中文字之間會出現連字號。 例如,針對路由範本為
/product-detail
(@page "/product-detail"
) 的ProductDetail
元件,我們會透過瀏覽器在相對 URL/product-detail
中提出要求。
†Pascal 命名法 (大駝峰式命名法) 是不含空格和標點符號的命名慣例,且每個單字的第一個字母會大寫,包括第一個單字。
•Kebab 大小寫是不含空格和標點符號的命名慣例,使用小寫字母和字組之間的虛線。
元件是一般的 C# 類別,而且可以放到專案內的任何位置。 產生網頁的元件通常位於 Components/Pages
資料夾中。 非網頁元件則經常放在 Components
資料夾中,或放在新增至專案的自訂資料夾中。
一般而言,元件的命名空間會衍生自應用程式的根命名空間,以及元件在應用程式內的位置 (資料夾)。 如果應用程式的根命名空間是 BlazorSample
,而且 Counter
元件位於 Components/Pages
資料夾中:
Counter
元件的命名空間為BlazorSample.Components.Pages
。- 元件的完整類型名稱為
BlazorSample.Components.Pages.Counter
。
對於保有元件的自訂資料夾,請將 @using
指示詞新增至父元件或新增至應用程式的 _Imports.razor
檔案。 下列範例會讓 AdminComponents
資料夾中的元件變為可用狀態:
@using BlazorSample.AdminComponents
注意
_Imports.razor
檔案中的 @using
指示詞只會套用至 Razor 檔案 (.razor
),而不會套用至 C# 檔案 (.cs
)。
using
支援別名語句。 在下列範例中,元件的公用 WeatherForecast
類別 GridRendering
會以應用程式其他地方的元件的形式 WeatherForecast
提供:
@using WeatherForecast = Components.Pages.GridRendering.WeatherForecast
您也可以使用元件的完整名稱來參考元件,如此便不必使用 @using
指示詞。 下列範例會直接參考應用程式 AdminComponents/Pages
資料夾中的 ProductDetail
元件:
<BlazorSample.AdminComponents.Pages.ProductDetail />
使用 Razor 撰寫的元件,其命名空間會以下列項目作為基礎 (依優先順序列出):
- Razor 檔案標記中的
@namespace
指示詞 (例如,@namespace BlazorSample.CustomNamespace
)。 - 專案在專案檔案中的
RootNamespace
(例如,<RootNamespace>BlazorSample</RootNamespace>
)。 - 專案命名空間和從專案根目錄到元件的路徑。 例如,架構會將
{PROJECT NAMESPACE}/Components/Pages/Home.razor
的專案命名空間BlazorSample
解析為 元件的 命名空間BlazorSample.Components.Pages
Home
。{PROJECT NAMESPACE}
是專案命名空間。 元件會遵循 C# 名稱繫結規則。Home
在此範例中的元件中,範圍中的元件都是所有元件:- 在相同資料夾中是
Components/Pages
。 - 專案根目錄中未明確指定不同命名空間的元件。
- 在相同資料夾中是
不支援下列項目:
global::
限定性條件。- 部分限定名稱。 例如,您無法將
@using BlazorSample
新增至元件,然後使用<Layout.NavMenu></Layout.NavMenu>
參考應用程式Components/Layout
資料夾 (Components/Layout/NavMenu.razor
) 中的NavMenu
元件。
元件的名稱必須以大寫字元開頭:
支援:ProductDetail.razor
支援:productDetail.razor
Blazor 文件中使用的通用 Blazor 命名慣例包括:
- 檔案路徑和檔案名會使用 Pascal 大小寫†並顯示在顯示程式碼範例之前。 如果路徑存在,表示一般資料夾位置。 例如,
Pages/ProductDetail.razor
代表ProductDetail
元件的檔案名稱為ProductDetail.razor
,且位於應用程式的Pages
資料夾中。 - 可路由元件的元件檔案路徑會比對基底案例中的 URL} ,而元件路由範本中文字之間會出現連字號。 例如,針對路由範本為
/product-detail
(@page "/product-detail"
) 的ProductDetail
元件,我們會透過瀏覽器在相對 URL/product-detail
中提出要求。
†Pascal 命名法 (大駝峰式命名法) 是不含空格和標點符號的命名慣例,且每個單字的第一個字母會大寫,包括第一個單字。
•Kebab 大小寫是不含空格和標點符號的命名慣例,使用小寫字母和字組之間的虛線。
元件是一般的 C# 類別,而且可以放到專案內的任何位置。 產生網頁的元件通常位於 Pages
資料夾中。 非網頁元件則經常放在 Shared
資料夾中,或放在新增至專案的自訂資料夾中。
一般而言,元件的命名空間會衍生自應用程式的根命名空間,以及元件在應用程式內的位置 (資料夾)。 如果應用程式的根命名空間是 BlazorSample
,而且 Counter
元件位於 Pages
資料夾中:
Counter
元件的命名空間為BlazorSample.Pages
。- 元件的完整類型名稱為
BlazorSample.Pages.Counter
。
對於保有元件的自訂資料夾,請將 @using
指示詞新增至父元件或新增至應用程式的 _Imports.razor
檔案。 下列範例會讓 AdminComponents
資料夾中的元件變為可用狀態:
@using BlazorSample.AdminComponents
注意
_Imports.razor
檔案中的 @using
指示詞只會套用至 Razor 檔案 (.razor
),而不會套用至 C# 檔案 (.cs
)。
using
支援別名語句。 在下列範例中,元件的公用 WeatherForecast
類別 GridRendering
會以應用程式其他地方的元件的形式 WeatherForecast
提供:
@using WeatherForecast = Pages.GridRendering.WeatherForecast
您也可以使用元件的完整名稱來參考元件,如此便不必使用 @using
指示詞。 下列範例會直接參考應用程式 Components
資料夾中的 ProductDetail
元件:
<BlazorSample.Components.ProductDetail />
使用 Razor 撰寫的元件,其命名空間會以下列項目作為基礎 (依優先順序列出):
- Razor 檔案標記中的
@namespace
指示詞 (例如,@namespace BlazorSample.CustomNamespace
)。 - 專案在專案檔案中的
RootNamespace
(例如,<RootNamespace>BlazorSample</RootNamespace>
)。 - 專案命名空間和從專案根目錄到元件的路徑。 例如,架構會將
{PROJECT NAMESPACE}/Pages/Index.razor
的專案命名空間BlazorSample
解析為 元件的 命名空間BlazorSample.Pages
Index
。{PROJECT NAMESPACE}
是專案命名空間。 元件會遵循 C# 名稱繫結規則。Index
在此範例中的元件中,範圍中的元件都是所有元件:- 在相同資料夾中是
Pages
。 - 專案根目錄中未明確指定不同命名空間的元件。
- 在相同資料夾中是
不支援下列項目:
global::
限定性條件。- 部分限定名稱。 例如,您無法將
@using BlazorSample
新增至元件,然後使用<Shared.NavMenu></Shared.NavMenu>
參考應用程式Shared
資料夾 (Shared/NavMenu.razor
) 中的NavMenu
元件。
部分類別支援
元件會以 C# 部分類別的形式產生,並使用下列任一方法來撰寫:
- 單一檔案包含一或多個
@code
區塊、HTML 標記和 Razor 標記中所定義的 C# 程式碼。 Blazor 專案範本會使用此單一檔案方法來定義其元件。 - HTML 和 Razor 標記會放在 Razor 檔案 (
.razor
) 中。 C# 程式碼會放在定義為部分類別的程式碼後置檔案 (.cs
) 中。
注意
定義元件特定樣式的元件樣式表是不同的檔案 (.css
)。 BlazorCSS 隔離稍後會在 ASP.NET CORE Blazor CSS 隔離中說明。
下列範例會顯示從 Blazor 專案範本產生的應用程式中,所具有的預設 Counter
元件與 @code
區塊。 標記和 C# 程式碼位於相同檔案中。 這是在撰寫元件時最常採用的方法。
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"
<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++;
}
}
下列 Counter
元件會使用具有部分類別的程式碼後置檔案,從 C# 程式碼分割簡報 HTML 和 Razor 標記。 一些組織和開發人員偏好將標記與 C# 程式碼分割,以組織其元件程式碼,以符合他們偏好的運作方式。 例如,組織的 UI 專家可以獨立于處理元件 C# 邏輯的另一位開發人員,獨立處理展示層。 使用自動產生的程式碼或來源產生器時,此方法也很有用。 如需詳細資訊,請參閱 部分類別和方法(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"
<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.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++;
}
}
}
_Imports.razor
檔案中的 @using
指示詞只會套用至 Razor 檔案 (.razor
),而不會套用至 C# 檔案 (.cs
)。 請視需要將命名空間新增至部分類別檔案。
元件所使用的典型命名空間:
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 Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
典型命名空間也包含應用程式的命名空間,以及對應至應用程式 Components
資料夾的命名空間:
using BlazorSample;
using BlazorSample.Components;
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;
典型命名空間也包含應用程式的命名空間,以及對應至應用程式 Shared
資料夾的命名空間:
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;
典型命名空間也包含應用程式的命名空間,以及對應至應用程式 Shared
資料夾的命名空間:
using BlazorSample;
using BlazorSample.Shared;
指定基底類別
@inherits
指示詞可用來指定元件的基底類別。 不同于只 從 C# 邏輯分割標記的部分類別 ,使用基類可讓您繼承 C# 程式碼,以便跨共用基類屬性和方法的元件群組使用。 使用基類可減少應用程式中的程式碼備援,並在將基底程式碼從類別庫提供給多個應用程式時很有用。 如需詳細資訊,請參閱 C# 和 .NET 中的繼承。
在下列範例中 BlazorRocksBase
,基類衍生自 ComponentBase 。
BlazorRocks.razor
:
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
@page "/blazor-rocks"
@inherits BlazorRocksBase
<h1>@BlazorRocksText</h1>
BlazorRocksBase.cs
:
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample
{
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample
{
public class BlazorRocksBase : ComponentBase
{
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
}
}
路由
在 Blazor 中實現路由功能的方法是,使用 @page
指示詞向應用程式中的每個可存取元件提供路由範本。 在編譯具有 @page
指示詞的 Razor 檔案時,所產生的類別會獲得 RouteAttribute 以指定路由範本。 在執行階段,路由器會搜尋具有 RouteAttribute 的元件類別,並轉譯其路由範本符合所要求 URL 的任何元件。
下列 HelloWorld
元件會使用 的 /hello-world
路由範本,且元件的轉譯網頁會到達相對 URL /hello-world
。
HelloWorld.razor
:
@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>
不論您是否有將元件新增至應用程式的 UI 導覽,上述元件都會透過瀏覽器在 /hello-world
中載入。 您也可以選擇將元件新增至 NavMenu
元件,讓後者的連結出現在應用程式的 UI 型導覽中。
針對上述 HelloWorld
元件,您可以將元件新增 NavLink
至 NavMenu
元件。 如需詳細資訊,包括 NavLink
和 NavMenu
元件的描述,請參閱 ASP.NET Core Blazor 路由和導覽。
加成
元件的 UI 會使用 Razor 語法來定義,此語法由 Razor 標記、C# 和 HTML 組成。 在編譯應用程式時,HTML 標記和 C# 轉譯邏輯會轉換為元件類別。 所產生的類別名稱與檔案的名稱相符。
元件類別的成員會定義於一或多個 @code
區塊中。 在 @code
區塊中,系統會使用 C# 來指定和處理元件狀態:
- 屬性和欄位的初始設定式。
- 父元件和路由參數所傳遞引數中的參數值。
- 使用者事件處理、生命週期事件和自訂元件邏輯的方法。
使用開頭為 @
符號的 C# 運算式即可在轉譯邏輯中使用元件成員。 例如,藉由在欄位名稱前面加上 @
即可轉譯 C# 欄位。 下列 Markup
元件會評估和轉譯:
headingFontStyle
,以取得標題元素的 CSS 屬性值font-style
。headingText
,以取得標題元素的內容。
Markup.razor
:
@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!";
}
注意
整個 Blazor 文件的範例會指定私人成員的 private
存取修飾詞。 私人成員的範圍僅限元件的類別。 不過,如果沒有任何存取修飾詞存在,C# 則會採用 private
存取修飾詞,因此您可以選擇是否要在自己的程式碼中將成員明確標記為「private
」。 如需存取修飾詞的詳細資訊,請參閱 存取修飾詞 (C# 程式設計指南)。
架構會將 Blazor 元件內部處理為 轉譯樹狀結構 ,這是元件 DOM 和 級聯樣式表單物件模型 (CSSOM) 的組合。 初次轉譯元件之後,便會重新產生元件的轉譯樹狀結構以回應事件。 Blazor 會拿新的轉譯樹狀結構與上一個轉譯樹狀結構做比較,並將任何修改套用至瀏覽器的 DOM 以供顯示。 如需詳細資訊,請參閱 ASP.NET Core Razor 元件轉譯。
C# 控制項結構、指示詞和指示詞屬性的 Razor 語法採用小寫 (範例:@if
、@code
、@bind
)。 屬性名稱則會大寫 (範例:例如 LayoutComponentBase.Body 的 @Body
)。
非同步方法 (async
) 不支援傳回 void
Blazor 架構不會追蹤 void
傳回的非同步方法 (async
)。 因此,如果傳回 void
,則不會攔截到例外狀況。 請一律從非同步方法傳回 Task。
巢狀元件
元件可以透過使用 HTML 語法來宣告元件,以包含其他元件。 使用元件的標記看起來像是 HTML 標籤,其中標籤名稱是元件類型。
請看一下下列 Heading
元件,其可供其他元件使用以顯示標題。
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";
}
HeadingExample
元件中的下列標記會在 <Heading />
標籤出現的位置轉譯上述 Heading
元件。
HeadingExample.razor
:
@page "/heading-example"
<Heading />
@page "/heading-example"
<Heading />
@page "/heading-example"
<Heading />
@page "/heading-example"
<Heading />
如果元件包含的 HTML 元素,其大寫的第一個字母與相同命名空間內的元件名稱不符,就會發出警告,指出該元素的名稱不符預期。 為元件的命名空間新增 @using
指示詞會讓元件變為可用狀態,如此便能解決警告。 如需詳細資訊,請參閱 元件名稱、類別名稱和命名空間 一節。
本節所示的 Heading
元件範例沒有 @page
指示詞,因此使用者無法透過在瀏覽器中直接要求來直接存取 Heading
元件。 不過,任何具有 @page
指示詞的元件都可以巢狀化到另一個元件中。 如果透過在 Razor 檔案頂端包含 @page "/heading"
而能夠直接存取 Heading
元件,則位於 /heading
和 /heading-example
的瀏覽器要求都會轉譯元件。
元件參數
「元件參數」會將資料傳遞至元件,其定義方式則是在元件類別上使用公用的 C# 屬性與 [Parameter]
屬性。 在下列範例中,內建的參考類型 (System.String) 和使用者定義的參考類型 (PanelBody
) 會以元件參數的形式來傳遞。
PanelBody.cs
:
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 = "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"
};
}
警告
支援為元件參數提供初始值,但請勿在第一次轉譯元件之後,建立會寫入到其自有參數的元件。 如需詳細資訊,請參閱 避免在 ASP.NET Core Blazor 中覆寫參數。
ParameterChild
元件的 Title
和 Body
元件參數會由轉譯元件執行個體的 HTML 標籤中的引數來設定。 下列 ParameterParent
元件會轉譯兩個 ParameterChild
元件:
- 第一個
ParameterChild
元件在轉譯時不會提供參數引數。 - 第二個
ParameterChild
元件會接收ParameterParent
元件中的Title
和Body
值,其會使用明確的 C# 運算式來設定PanelBody
屬性的值。
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" })" />
@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" })" />
@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" })" />
@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
元件未提供元件參數值時,下列從 ParameterParent
元件轉譯而來的 HTML 標記會顯示 ParameterChild
元件的預設值。 當 ParameterParent
元件提供元件參數值時,這些值便會取代 ParameterChild
元件的預設值。
注意
為了清楚起見,下列轉譯的 HTML 標記中未顯示轉譯的 CSS 樣式類別。
<h1>Child component (without attribute values)</h1>
<div>
<div>Set By Child</div>
<div>Set by child.</div>
</div>
<h1>Child component (with attribute values)</h1>
<div>
<div>Set by Parent</div>
<div>Set by parent.</div>
</div>
將方法的 C# 欄位、屬性或結果指派給元件參數做為 HTML 屬性值。 屬性的值通常可以是符合參數類型的任何 C# 運算式。 屬性的值可以選擇性地以 Razor 保留 @
符號 領先,但並非必要。
如果元件參數的類型為字串,則屬性值預設會視為 C# 字串常值。 如果您想要改為指定 C# 運算式,請使用 @
前置詞。
下列 ParameterParent2
元件會顯示上述 ParameterChild
元件的四個執行個體,並將其 Title
參數值設定為:
title
欄位的值。GetTitle
C# 方法的結果。- 使用 ToLongDateString 並以完整格式表示的當前本機日期,其會使用隱含的 C# 運算式。
panelData
物件的Title
屬性。
不建議將 @
前置詞用於常值 (例如布林值)、關鍵字 (例如 this
) 或 null
,但如果您想要的話,還是可以選擇如此使用。 例如,IsFixed="@true"
雖不常見,但仍受到支援。
根據 HTML5 的規格,在大部分情況下,您可以選擇是否在參數屬性值外加上引號。 例如,Value=this
會受到支援,Value="this"
則不會。 不過,我們還是建議使用引號,因為這麼做不僅方便記住,也廣為 Web 型技術所採用。
在整個文件中,程式碼範例:
- 一律使用引號。 範例:
Value="this"
. - 使用前置
@
詞搭配非精簡字元, 即使它是選擇性 的。 範例:Count="@ct"
,其中ct
是數位型別變數。Count="ct"
是有效的文體方法,但檔和範例不會採用慣例。 - 一律避免
@
在運算式外部 Razor 的常值。 範例:IsFixed="true"
.
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";
}
}
@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";
}
}
@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";
}
}
@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";
}
}
注意
將 C# 成員指派給元件參數時,請勿在參數的 HTML 屬性前面加上 @
。
正確 ( Title
是字串參數, Count
是數位型別參數):
<ParameterChild Title="@title" Count="@ct" />
<ParameterChild Title="@title" Count="ct" />
不正確:
<ParameterChild @Title="@title" @Count="@ct" />
<ParameterChild @Title="@title" @Count="ct" />
和在 Razor 頁面 (.cshtml
) 中不同,Blazor 無法在轉譯元件時於 Razor 運算式中執行非同步工作。 這是因為 Blazor 的設計目的是轉譯互動式 UI。 在互動式 UI 中,畫面一定要顯示內容,因此封鎖轉譯流程並不合理。 相反地,非同步工作會在其中一個非同步生命週期事件期間執行。 在每個非同步生命週期事件過後,元件可能會重新轉譯。 下列 Razor 語法不受支援:
<ParameterChild Title="@await ..." />
上述範例中的程式碼會在建置應用程式時產生「編譯器錯誤」:
「await」運算子只能用於非同步方法。 請考慮使用「async」修飾詞標記這個方法,並將其傳回類型變更為「Task」。
若要以非同步方式取得上述範例中 Title
參數的值,元件可以使用 OnInitializedAsync
生命週期事件,如下列範例所示:
<ParameterChild Title="@title" />
@code {
private string? title;
protected override async Task OnInitializedAsync()
{
title = await ...;
}
}
如需詳細資訊,請參閱 ASP.NET Core Razor 元件生命週期。
不支援使用明確的 Razor 運算式來串連文字與運算式結果以指派給參數。 下列範例會試圖將文字「Set by
」與物件的屬性值串連起來。 雖然 Razor 頁面 (.cshtml
) 支援此語法,但若要指派給子系在元件中的 Title
參數則會無效。 下列 Razor 語法不受支援:
<ParameterChild Title="Set by @(panelData.Title)" />
上述範例中的程式碼會在建置應用程式時產生「編譯器錯誤」:
元件屬性 (attribute) 不支援複雜內容 (混合 C# 和標記)。
若要支援撰寫值的指派,請使用方法、欄位或屬性 (property)。 下列範例會在 C# 方法 GetTitle
中執行「Set by
」和物件屬性 (property) 值的串連:
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";
}
}
@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";
}
}
@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";
}
}
@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";
}
}
如需詳細資訊,請參閱 ASP.NET Core 的 Razor 語法參考。
警告
支援為元件參數提供初始值,但請勿在第一次轉譯元件之後,建立會寫入到其自有參數的元件。 如需詳細資訊,請參閱 避免在 ASP.NET Core Blazor 中覆寫參數。
元件參數應該宣告為自動屬性,這表示其不應該在其 get
或 set
存取子中包含自訂邏輯。 例如,下列 StartData
屬性是自動屬性:
[Parameter]
public DateTime StartData { get; set; }
請勿將自訂邏輯放在 get
或 set
存取子中,因為元件參數純粹是作為父元件用來將資訊流向子元件的通道而已。 如果子元件屬性的 set
存取子包含的邏輯會導致父元件重新轉譯,則會產生無限循環的轉譯。
若要轉換所接收的參數值:
- 讓參數屬性仍作為自動屬性,以代表所提供的未經處理資料。
- 建立不同的屬性或方法,以根據參數屬性提供經過轉換的資料。
覆寫 OnParametersSetAsync
以在每次收到新資料時轉換所接收的參數。
支援在元件參數中寫入初始值,因為指派初始值並不會干擾 Blazor 自動轉譯元件。 在元件中,將目前的本機 DateTime 與 DateTime.Now 指派給 StartData
屬於有效的語法:
[Parameter]
public DateTime StartData { get; set; } = DateTime.Now;
在初始指派 DateTime.Now 之後,請勿在開發人員程式碼的 StartData
中指派值。 如需詳細資訊,請參閱 避免在 ASP.NET Core Blazor 中覆寫參數。
套用 [EditorRequired]
屬性以指定必要的元件參數。 如果未提供參數值,編輯器或建置工具可能會向使用者顯示警告。 這個屬性 (attribute) 只會在也標記上 [Parameter]
屬性 (attribute) 的屬性 (property) 上有效。 在設計階段以及在建置應用程式時,會強制執行 EditorRequiredAttribute。 屬性 (attribute) 不會在執行階段強制執行,而且也不會保證非 null
參數值。
[Parameter]
[EditorRequired]
public string? Title { get; set; }
也支援單行屬性 (attribute) 清單:
[Parameter, EditorRequired]
public string? Title { get; set; }
請勿在 required
元件參數屬性上使用 修飾 詞或 init
存取子 。 元件通常會使用 反映來具現化和指派的參數值,這會略過和設計成的保證 required
init
。 請改用 [EditorRequired]
屬性 來指定必要的元件參數。
請勿在 init
元件參數屬性上使用 存取子 ,因為將元件參數值設定為 ParameterView.SetParameterProperties 使用 反映 ,這會略過僅限 init 的 setter 限制。 [EditorRequired]
使用 屬性 來指定必要的元件參數。
請勿在 init
元件參數屬性上使用 存取子 ,因為將元件參數值設定為 ParameterView.SetParameterProperties 使用 反映 ,這會略過僅限 init 的 setter 限制。
Tuples
(API 文件) 支援用於元件參數和 RenderFragment
類型。 下列元件參數範例會在 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 ,如下列範例所示:
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);
}
引用 ©2005 Universal Pictures: Serenity (Nathan Fillion)
路由參數
元件可以在 @page
指示詞的路由範本中指定路由參數。 Blazor 路由器會使用路由參數來填入對應的元件參數。
支援使用選擇性路由參數。 在下列範例中,text
選擇性參數會將路由區段的值指派給元件的 Text
屬性。 如果區段不存在,則在 OnInitialized
生命週期方法中,Text
的值會設定為「fantastic
」。
不支援選擇性路由參數,因此下列範例會套用兩 @page
個指示詞。 第一個 @page
指示詞會允許導覽至沒有路由參數的元件。 第二個 @page
指示詞會接收 {text}
路由參數,並將值指派給 Text
屬性。
RouteParameter.razor
:
@page "/route-parameter/{text?}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string? Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
@page "/route-parameter/{text?}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string? Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
@page "/route-parameter/{text?}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
@page "/route-parameter"
@page "/route-parameter/{text}"
<h1>Blazor is @Text!</h1>
@code {
[Parameter]
public string Text { get; set; }
protected override void OnInitialized()
{
Text = Text ?? "fantastic";
}
}
如需可跨多個資料夾界限來擷取路徑的 catch-all 路由參數 ({*pageRoute}
) 的相關資訊,請參閱 ASP.NET Core Blazor 路由和導覽。
子內容轉譯片段
元件可以設定另一個元件的內容。 指派方元件會提供子元件的開頭和結束標籤之間的內容。
在下列範例中,RenderFragmentChild
元件具有 ChildContent
元件參數,此參數代表要轉譯為 RenderFragment 的 UI 區段。 ChildContent
在元件 Razor 標記中的位置,正是內容在最終 HTML 輸出中的轉譯位置。
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; }
}
下列 RenderFragmentParent
元件會藉由將內容放在子元件的開頭和結束標籤內,來提供用於轉譯 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>
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
@page "/render-fragment-parent"
<h1>Render child content</h1>
<RenderFragmentChild>
Content of the child component is supplied
by the parent component.
</RenderFragmentChild>
由於 Blazor 轉譯子內容的方式,如果 RenderFragmentChild
元件的內容中使用遞增迴圈變數,則在 for
迴圈內轉譯元件需要用到本機索引變數。 下列範例可以新增至上述 RenderFragmentParent
元件:
<h1>Three children with an index variable</h1>
@for (int c = 0; c < 3; c++)
{
var current = c;
<RenderFragmentChild>
Count: @current
</RenderFragmentChild>
}
或者,使用 foreach
迴圈並搭配 Enumerable.Range,而不是使用 for
迴圈。 下列範例可以新增至上述 RenderFragmentParent
元件:
<h1>Second example of three children with an index variable</h1>
@foreach (var c in Enumerable.Range(0,3))
{
<RenderFragmentChild>
Count: @c
</RenderFragmentChild>
}
轉譯片段可用來在整個 Blazor 應用程式中轉譯子內容,下列文章和文章內的章節會有範例進行相關說明:
注意
Blazor 架構的內建 Razor 元件會使用相同的 ChildContent
元件參數慣例來設定其內容。 若要查看設定子內容的元件,請在 API 文件中搜尋元件參數屬性名稱 ChildContent
(使用搜尋字詞「ChildContent」來篩選 API)。
轉譯可重複使用轉譯邏輯的片段
您可以透過單純重複使用轉譯邏輯的方式來分解子元件。 在任何元件的 @code
區塊中,定義 RenderFragment,並視需要從任何位置轉譯片段任意次數:
@RenderWelcomeInfo
<p>Render the welcome info a second time:</p>
@RenderWelcomeInfo
@code {
private RenderFragment RenderWelcomeInfo = @<p>Welcome to your new app!</p>;
}
如需詳細資訊,請參閱重複使用轉譯邏輯。
擷取元件的參考
元件參考可讓您參考用於發出命令的元件執行個體。 若要擷取元件參考:
- 將
@ref
屬性新增至子元件。 - 定義與子元件相同類型的欄位。
元件轉譯時,欄位會填入元件執行個體。 接著,您便可以叫用執行個體上的 .NET 方法。
請考慮下列會在呼叫其 ChildMethod
時記錄訊息的 ReferenceChild
元件。
ReferenceChild.razor
:
@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);
}
}
只有在元件已轉譯且其輸出包含 ReferenceChild
的元素之後,才會填入元件參考。 在元件轉譯之前,不會有對象可以參考。
若要在元件完成轉譯之後操作元件參考,請使用 OnAfterRender
或 OnAfterRenderAsync
方法。
若要搭配事件處理常式來使用參考變數,請使用 Lambda 運算式,或在 OnAfterRender
或 OnAfterRenderAsync
方法中指派事件處理常式委派。 這可確保在指派事件處理常式之前,會先指派參考變數。
下列 Lambda 方法會使用上述 ReferenceChild
元件。
ReferenceParent1.razor
:
@page "/reference-parent-1"
<button @onclick="@(() => childComponent?.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild? childComponent;
}
@page "/reference-parent-1"
<button @onclick="@(() => childComponent?.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild? childComponent;
}
@page "/reference-parent-1"
<button @onclick="@(() => childComponent.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
}
@page "/reference-parent-1"
<button @onclick="@(() => childComponent.ChildMethod(5))">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
}
下列委派方法會使用上述 ReferenceChild
元件。
ReferenceParent2.razor
:
@page "/reference-parent-2"
<button @onclick="@(() => callChildMethod?.Invoke())">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild? childComponent;
private Action? callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent?.ChildMethod(5);
}
}
@page "/reference-parent-2"
<button @onclick="@(() => callChildMethod?.Invoke())">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild? childComponent;
private Action? callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent?.ChildMethod(5);
}
}
@page "/reference-parent-2"
<button @onclick="callChildMethod">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
private Action callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent.ChildMethod(5);
}
}
@page "/reference-parent-2"
<button @onclick="callChildMethod">
Call <code>ReferenceChild.ChildMethod</code> with an argument of 5
</button>
<ReferenceChild @ref="childComponent" />
@code {
private ReferenceChild childComponent;
private Action callChildMethod;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
callChildMethod = CallChildMethod;
}
}
private void CallChildMethod()
{
childComponent.ChildMethod(5);
}
}
雖然擷取元件參考會使用類似於擷取元素參考的語法,但擷取元件參考不是 JavaScript 的 Interop 功能。 元件參考不會傳遞至 JavaScript 程式碼。 元件參考只會用於 .NET 程式碼。
重要
請勿使用元件參考來變動子元件的狀態。 請改用一般宣告式元件參數,將資料傳遞至子元件。 使用元件參數會導致子元件在正確時間自動重新轉譯。 如需詳細資訊,請參閱元件參數一節和 ASP.NET Core Blazor 資料繫結一文。
套用屬性
您可以使用 @attribute
指示詞將屬性套用至元件。 下列範例會將 [Authorize]
屬性套用至元件的類別:
@page "/"
@attribute [Authorize]
條件式 HTML 元素屬性
HTML 元素屬性 (attribute) 屬性 (property) 會根據 .NET 值有條件地進行設定。 如果值為 false
或 null
,則不會設定屬性 (property)。 如果值為 true
,則會設定屬性 (property)。
在下列範例中,IsCompleted
會判斷是否已設定 <input>
元素的 checked
屬性 (property)。
ConditionalAttribute.razor
:
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
@page "/conditional-attribute"
<label>
<input type="checkbox" checked="@IsCompleted" />
Is Completed?
</label>
<button @onclick="@(() => IsCompleted = !IsCompleted)">
Change IsCompleted
</button>
@code {
[Parameter]
public bool IsCompleted { get; set; }
}
如需詳細資訊,請參閱 ASP.NET Core 的 Razor 語法參考。
警告
aria-pressed
之類的某些 HTML 屬性 (attribute) 在 .NET 類型為 bool
時無法正常運作。 在這些情況下,請使用 string
類型,而非使用 bool
。
原始 HTML
字串一般會使用 DOM 文字節點來進行轉譯,這表示其可能包含的任何標記都會遭到忽略並視為常值文字。 若要轉譯原始 HTML,請將 HTML 內容包裝到 MarkupString 值內。 此值會剖析為 HTML 或 SVG,並插入到 DOM。
警告
針對從任何不受信任的來源所建構的原始 HTML 進行轉譯會有安全性風險,請一律避免此行為。
下列範例示範如何使用 MarkupString 類型,將靜態 HTML 內容的區塊新增至元件的轉譯輸出。
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>";
}
@page "/markup-string-example"
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
@page "/markup-string-example"
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
@page "/markup-string-example"
@((MarkupString)myMarkup)
@code {
private string myMarkup =
"<p class=\"text-danger\">This is a dangerous <em>markup string</em>.</p>";
}
Razor 範本
您可以使用 Razor 範本語法來定義 UI 程式碼片段,從而定義轉譯片段。 Razor 範本會使用下列格式:
@<{HTML tag}>...</{HTML tag}>
下列範例說明如何直接在元件中指定 RenderFragment 和 RenderFragment<TValue> 的值並轉譯範本。 轉譯片段也可以作為引數傳遞至樣板化元件。
RazorTemplate.razor
:
@page "/razor-template"
@timeTemplate
@petTemplate(new Pet { Name = "Nutty Rex" })
@code {
private RenderFragment timeTemplate = @<p>The time is @DateTime.Now.</p>;
private RenderFragment<Pet> petTemplate = (pet) => @<p>Pet: @pet.Name</p>;
private class Pet
{
public string? Name { get; set; }
}
}
@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; }
}
}
上述程式碼的轉譯輸出:
<p>The time is 4/19/2021 8:54:46 AM.</p>
<p>Pet: Nutty Rex</p>
靜態資產
Blazor 會遵循靜態資產的 ASP.NET Core 應用程式慣例。 靜態資產位於專案的 web root
(wwwroot
) 資料夾內,或是 wwwroot
資料夾底下的資料夾內。
請使用基底相對路徑 (/
) 來參考靜態資產的 Web 根目錄。 在下列範例中,logo.png
實際位於 {PROJECT ROOT}/wwwroot/images
資料夾中。 {PROJECT ROOT}
是應用程式的專案根目錄。
<img alt="Company logo" src="/images/logo.png" />
元件不支援波狀符號正斜線標記法 (~/
)。
如需如何設定應用程式基底路徑的相關資訊,請參閱裝載及部署 ASP.NET Core Blazor。
元件不支援標籤協助程式
元件不支援Tag Helpers
。 若要在 Blazor 中提供類似標籤協助程式的功能,請建立功能與標籤協助程式相同的元件,並改用該元件。
可縮放向量圖形 (SVG) 影像
由於 Blazor 會轉譯 HTML,因此包括可縮放向量圖形 (SVG) 影像 (.svg
) 在內的瀏覽器支援影像可透過 <img>
標籤而獲得支援:
<img alt="Example image" src="image.svg" />
同樣地,樣式表檔案的 CSS 規則 (.css
) 也支援 SVG 影像:
.element-class {
background-image: url("image.svg");
}
Blazor 會支援 <foreignObject>
元素,以便顯示 SVG 內的任意 HTML。 標記可以代表任意 HTML、RenderFragment 或 Razor 元件。
下列範例會示範:
- 顯示
string
(@message
)。 <input>
元素和value
欄位的雙向繫結。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;
}
空白字元轉譯行為
除非 @preservewhitespace
指示詞與 true
值搭配使用,否則如果有下列情況,系統預設會移除額外的空白字元:
- 在元素內前置或後置。
- 在 RenderFragment/RenderFragment<TValue> 參數內前置或後置 (例如,子內容傳遞至另一個元件)。
- 其在 C# 程式碼區塊之前或之後,例如
@if
或@foreach
。
使用 CSS 規則時,移除空白字元可能會影響經過轉譯的輸出,例如 white-space: pre
。 若要停用此效能最佳化功能並保留空白字元,請採取下列其中一個動作:
- 在 Razor 檔案 (
.razor
) 頂端新增@preservewhitespace true
指示詞,以將喜好設定套用至特定元件。 - 在
_Imports.razor
檔案內新增@preservewhitespace true
指示詞,以將喜好設定套用至子目錄或整個專案。
在大部分情況下,您不需要採取任何動作,因為應用程式通常會繼續正常運作 (但速度會更快)。 如果移除空白字元會導致特定元件發生轉譯問題,請在該元件中使用 @preservewhitespace true
來停用此最佳化。
空白字元會保留在元件的來源標記中。 只有空白字元的文字會在瀏覽器的 DOM 中轉譯,即使沒有視覺效果也是如此。
請考慮下列元件標記:
<ul>
@foreach (var item in Items)
{
<li>
@item.Text
</li>
}
</ul>
上述範例會轉譯下列不必要的空白字元:
- 位於
@foreach
程式碼區塊外部。 - 在
<li>
元素周圍。 - 在
@item.Text
輸出周圍。
100 個項目的清單會產生超過 400 個空白字元區域。 再多的空白字元也不會在視覺上影響轉譯的輸出。
在轉譯元件的靜態 HTML 時,不會保留標籤內的空白字元。 例如,在元件 Razor 檔案中檢視下列 <img>
標籤的轉譯輸出 (.razor
):
<img alt="Example image" src="img.png" />
不會從上述標記保留空白字元:
<img alt="Example image" src="img.png" />
轉譯靜態根 Razor 元件
根 Razor 元件 是載入應用程式所建立之任何元件階層的第一個元件。
在從 Blazor Web App 專案範本建立的應用程式中, App
元件 ( App.razor
) 會透過針對伺服器端 Program
檔案中呼叫 MapRazorComponents<TRootComponent>
所宣告的類型參數,指定為預設根元件。 下列範例示範使用 App
元件做為根元件,這是從 Blazor 專案範本建立之應用程式的預設值:
app.MapRazorComponents<App>();
在從 Blazor Server 專案範本建立的應用程式中, App
元件 ( App.razor
) 會使用 元件標籤協助程式 ,在 中 Pages/_Host.cshtml
指定為預設根元件:
<component type="typeof(App)" render-mode="ServerPrerendered" />
在從 Blazor WebAssembly 專案範本建立的應用程式中, App
元件 ( App.razor
) 會指定為檔案中的 Program
預設根元件:
builder.RootComponents.Add<App>("#app");
在上述程式碼中,CSS 選取器 ,表示 App
中已使用 app
id
wwwroot/index.html
<div>
的 指定元件: #app
<div id="app">...</app>
MVC 和 Razor Pages 應用程式也可以使用 元件標籤協助程式 來註冊靜態轉譯 Blazor WebAssembly 的根元件:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
靜態轉譯的元件只能新增至應用程式。 之後無法移除或更新它們。
如需詳細資訊,請參閱以下資源: