翻譯自 Waqas Anwar 2021年3月19日的文章 《A Beginner’s Guide to Blazor Components》 [1]

Blazor 應用程式是元件的組合,這些元件不僅負責呈現使用者介面,還協同工作以促進使用者互動。它們是 Blazor 應用程式的主要構建塊,大多數 Blazor 功能都是圍繞元件展開的。在本教程中,我將向您詳細介紹元件,並向您展示在 Blazor 應用程式中建立和使用元件的多種技術。

下載原始碼[2]

Blazor 元件概述

Blazor 元件是 UI 的一個自包含部分,例如一個頁面、一個側邊欄選單、一個聯絡人表單或儀表盤小工具等。它包括用於呈現 UI 的 HTML 標籤和用於處理資料或處理使用者事件的 C# 程式碼。元件可以相互巢狀,也可以在專案中重用,甚至可以跨多個專案重用。Blazor 元件是作為 Razor 元件實現的,這正是它們使用 Razor 語法並具有 .razor 副檔名的原因。

為了理解 Blazor 元件的結構及其工作方式,讓我們回顧一下 Counter.razor 元件(如果您在 Visual Studio 2019 中使用 Blazor App 模板,它會自動為我們生成)。下面是 Counter.razor 的完整程式碼。

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

檔案中的第一行使用了 Razor @page 指令來指定元件的路由。這意味著 Counter 元件是頁面級或可路由元件,可以在瀏覽器中使用 URL 末尾的 /counter 路徑來訪問它。如果我們不指定 @page 指令,則該元件將變為子元件,可以通過將其巢狀在其他元件中來使用它。

@page "/counter"

如下所示,我們還可以宣告多個 @page 級別的指令。這將允許我們使用兩個 URL 訪問元件。

@page "/counter"
@page "/mycounter"

@page 指令之後,是用於指定該元件 UI 的 HTML 標記。這些標記可以使用 Razor 語法動態地使用表示式、條件或迴圈來渲染 HTML。在上述的 Counter 元件示例中,其 UI 包含一個標題 (h1)、一個段落 (p) 和一個按鈕 (button) 元素。段落 (p) 元素使用 Razor 語法來輸出 C# 程式碼塊中定義的 currentCount 變數的值。

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

按鈕 (button) 元素通過呼叫方法 IncrementCount 來響應使用者單擊操作,該方法也定義在程式碼塊中。

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

最後,是一個程式碼塊,每次呼叫 IncrementCount 方法時,我們簡單地將 currentCount 變數的值加 1。

@code {
private int currentCount = 0; private void IncrementCount()
{
currentCount++;
}
}

當 Blazor 應用程式進行編譯時,HTML 標記和 C# 程式碼將轉換成一個元件類,類名稱與元件的檔名相對應。該類的成員是我們在 @code 中定義的相同的變數和方法。允許使用多個 @code 塊,所有這些程式碼塊在編譯後會合併進同一組件類。

在 Visual Studio 2019 中建立 Blazor 元件

如果您要建立一個頁面級元件,請右鍵單擊 Pages 資料夾並選擇 新增 > Razor 元件... 選單選項。

您也可以在解決方案資源管理器中右鍵單擊專案名稱,然後使用 Razor 元件 模板建立一個元件。

讓我們建立一個檔名為 Calculator.razor 的元件,並新增以下程式碼。

Calculator.razor

@page "/calculator"

<h3>Calculator</h3>

<div class="form-group">
<label for="number1">Number 1</label>
<input type="number" class="form-control" id="number1" @bind="number1">
</div>
<div class="form-group">
<label for="number2">Number 2</label>
<input type="number" class="form-control" id="number2" @bind="number2">
</div>
<div class="form-group">
<label><b>Total: </b>@total</label>
</div> <button class="btn btn-primary" @onclick="Calculate">Calculate</button> @code {
private int number1 = 0;
private int number2 = 0;
private int total = 0; private void Calculate()
{
total = number1 + number2;
}
}

@code 塊具有三個私有變數和一個 Calculate 方法。Calculate 方法簡單地將 number1number2 的和賦值給 total 變數。

HTML 標記中有兩個輸入框,它們使用 @bind 屬性來繫結 number1number2 變數:

<input type="number" class="form-control" id="number1" @bind="number1">

變數 total 的值使用 Razor 語法 @total 渲染在頁面上:

<label><b>Total: </b>@total</label>

最後,是一個按鈕元素,它將 Calculate 方法繫結到 @onclick 事件。每當使用者點選按鈕時,就會呼叫 Calculate 方法,頁面上的 total 變數的值將更新。

<button class="btn btn-primary" @onclick="Calculate">Calculate</button>

為了輕鬆訪問您的 Calculator 元件,可以通過在 NavMenu.razor 元件中新增以下標記,在應用程式側邊欄中新增 Calculator 元件。

<li class="nav-item px-3">
<NavLink class="nav-link" href="calculator">
<span class="oi oi-calculator" aria-hidden="true"></span> Calculator
</NavLink>
</li>

F5 執行您的應用程式,您應該會看到如下所示的頁面。嘗試在輸入框中輸入一些數字,您應該能看到頁面上顯示的數字之和。點選 Calculate 按鈕運行了服務端的 C# 程式碼,卻並沒有瀏覽器回傳或頁面重新整理。一切都感覺那麼流暢和快速,就像您在瀏覽器中使用 JavaScript 進行計算一樣。

如果您想檢驗一下程式碼是在服務端上執行的,只需嘗試在 Calculate 方法中新增一個斷點,然後再次按下 F5。這次,當您點選 Calculate 按鈕時,您將看到程式碼執行到斷點處停止,您還可以在 tooltips 中看到使用者輸入,如下圖所示:

拆分 Blazor 元件中的標籤和程式碼

如果您建立的是小型元件,那麼您可能希望在單個 .razor 檔案中編寫所有 C# 程式碼;但如果您有大量的邏輯要寫並且為了更好的程式碼維護,您希望將 C# 程式碼與 HTML 標籤分開,那麼可以通過以下兩種方式來實現。

使用基類拆分元件

使用這種方式,您可以建立一個獨立的類,該類應該從 ComponentBase 類派生。然後,您可以將元件中的屬性和方法從 @code 塊移動到這個新建立的類,最後,您可以使用 @inherits 指令來指定元件的基類。讓我們將這種方式應用於我們上面建立的 Calculator 元件。在專案中建立一個 CalculatorBase 類,並將 C# 程式碼從 Calculator.razor 移動到這個新類中。

CalculatorBase.cs

public class CalculatorBase : ComponentBase
{
private int number1 = 0;
private int number2 = 0;
private int total = 0; private void Calculate()
{
total = number1 + number2;
}
}

然後在 Calculator.razor 檔案的頂部新增 @inherits 指令,如下:

Calculator.razor

@page "/calculator"
@inherits CalculatorBase <h3>Calculator</h3> <div class="form-group">
<label for="number1">Number 1</label>
<input type="number" class="form-control" id="number1" @bind="number1">
</div>
<div class="form-group">
<label for="number2">Number 2</label>
<input type="number" class="form-control" id="number2" @bind="number2">
</div>
<div class="form-group">
<label><b>Total: </b>@total</label>
</div> <button class="btn btn-primary" @onclick="Calculate">Calculate</button> @code { }

此時如果您嘗試構建應用程式,則會遇到很多錯誤抱怨欄位和方法的可訪問性。

出現上述所有錯誤的原因是 Calculator 元件繼承自 CalculatorBase 類,而我們在 CalculatorBase 類中貼上的屬性和方法是 private。為了確保子元件可以訪問這些欄位和方法,您需要將它們宣告為 public

public class CalculatorBase : ComponentBase
{
public int number1 = 0;
public int number2 = 0;
public int total = 0; public void Calculate()
{
total = number1 + number2;
}
}

譯者注:

基類中的欄位和方法改為 protected, 在 .razor 中也是可以的訪問的。

CalculatorBase 類必須包含在一個名稱空間中,否則會報錯。

使用部分類拆分元件

Blazor 元件生成為部分類,這意味著我們可以建立一個與我們的元件同名的 partial 類,並將所有 C# 程式碼移動到該部分類中。然後,此部分類將成為程式碼隱藏檔案,該檔案中宣告的欄位和屬性可在 Blazor 元件中直接使用。讓我們建立一個類 Calculator.razor.cs,並將 Calculator 的程式碼放在這個新類中。

Calculator.razor.cs

public partial class Calculator
{
public int number1 = 0;
public int number2 = 0;
public int total = 0; public void Calculate()
{
total = number1 + number2;
}
}

如果啟用了檔案巢狀,您將看到 Visual Studio 會自動將元件和程式碼隱藏檔案顯示在一起。

再次執行應用程式,Calculator 會以前面相同的方式工作。

建立和使用子元件

Blazor 子元件是沒有 @page 指令的元件。這些元件可以使用標準的 HTML 語法包含在其他元件中。然後,我們可以通過在頁面上新增元件來構建複雜的 UI,我們甚至可以在同一個頁面上新增同一子元件的多個例項。如果一個子元件可能在多個父元件或頁面中重複使用,那麼最好將它放在 Shared 資料夾中。讓我們在 Shared 資料夾中建立一個簡單的 Heading.razor 子元件,並在其中新增以下程式碼。

Heading.razor

<h3>Calculator</h3>

接下來,將父元件 Calculator.razor 中的 h3 元素替換為 <Heading /> 元素。執行應用程式,您會看到 h3 標題從子元件中渲染到了頁面上。

Calculator.razor

@page "/calculator"
@inherits CalculatorBase <Heading /> <div class="form-group">
<label for="number1">Number 1</label>
<input type="number" class="form-control" id="number1" @bind="number1">
</div>
<div class="form-group">
<label for="number2">Number 2</label>
<input type="number" class="form-control" id="number2" @bind="number2">
</div>
<div class="form-group">
<label><b>Total: </b>@total</label>
</div> <button class="btn btn-primary" @onclick="Calculate">Calculate</button>

您甚至可以通過複製和貼上相同的 <Heading /> 元素來新增子元件的多個例項。

<Heading />
<Heading />
<Heading />

現在,如果您執行應用程式,您將會在頁面上看到三個 h3 標題。

自定義帶引數的 Blazor 元件

只是生成具有相同內容的靜態元件不是很有用。如果我們可以將一些資料傳遞給元件,而不僅僅是自定義它生成的 UI,還自定義其行為或功能,那就更好了。我們可以使用引數來自定義 Blazor 元件。這些引數可以是簡單的 intbool 等,也可以是複雜的 CustomerOrder 等。一旦聲明瞭引數,我們便可以使用屬性將資料傳遞給元件。讓我們通過在 Heading 元件中宣告一個簡單的 Title 引數來學習一下這個概念。要指定一個引數,我們要將 [Parameter] 特性附加到一個屬性上。

Heading.razor

<h3>@Title</h3>

@code {
[Parameter]
public string Title { get; set; } = "Default Title";
}

我們還為 Title 屬性設定了一個預設值 Default Title,當未提供 Title 時,則顯示該預設字串。

Visual Studio 智慧感知也可以提示元件引數,因此我們不需要記憶這些引數,這很有用。

我們可以通過傳遞任意字串作為 Title 的值來從外部自定義 Title,Heading 元件將自動渲染傳遞給它的不同字串。

<Heading Title="Calculator" />

我們還可以使用表示式從父元件到子元件傳遞資料。讓我們建立另外一個子元件 CalculatorTotal.razor,並向其新增以下程式碼。

CalculatorTotal.razor

<label><b>Total: </b>@Total</label>

@code {
[Parameter]
public int Total { get; set; }
}

現在,您可以使用我們在父 Calculator 控制器中宣告和設定的 @total 欄位來傳遞 Total 的值。

Calculator.razor

@page "/calculator"

<Heading Title="Calculator" />

<div class="form-group">
<label for="number1">Number 1</label>
<input type="number" class="form-control" id="number1" @bind="number1">
</div>
<div class="form-group">
<label for="number2">Number 2</label>
<input type="number" class="form-control" id="number2" @bind="number2">
</div>
<div class="form-group">
<CalculatorTotal Total="@total"/>
</div> <button class="btn btn-primary" @onclick="Calculate">Calculate</button>

將路由引數傳遞給 Blazor 元件

Blazor 元件還可以接受在 @page 指令中提供的來自路由模板的引數。路由器使用路由引數自動填充相應的元件引數。

讓我們看一個如何通過路由將資料傳遞給元件的示例。建立一個新的名為 MathTable.razor 的 Blazor 元件並新增以下程式碼。

MathTable.razor

@page "/MathTable/{number:int}"

<h3>Math Table</h3>

<table class="table table-bordered w-25">
@for (int i = 1; i <= 10; i++)
{
<tr>
<td>@Number</td>
<td>x</td>
<td>@i</td>
<td>=</td>
<td>@(Number * i)</td>
</tr>
}
</table> @code {
[Parameter]
public int Number { get; set; }
}

我們指定了一個帶有 int 引數 number 的路由模板:

@page "/MathTable/{number:int}"

該路由引數將自動對映到以下元件引數:

[Parameter]
public int Number { get; set; }

在 HTML 標記中,我使用 number 引數生成一個數學公式表。執行專案並嘗試在路由 URL 中傳遞不同的數字,您將看到根據每一引數值更新的數學公式表。

總結

在本教程中,我介紹了 Blazor 元件的基礎知識。我試圖用易於理解的示例來演示每個概念,以便您可以快速學習基本概念。 Blazor 元件提供的功能比我在本教程中介紹的要多得多,而且還有許多其他與 Blazor 元件相關的高階主題。在接下來的幾周裡,我將嘗試寫更多關於 Blazor 的文章,因此請繼續訪問我的網站以學習有關 Blazor 的更多知識。

相關閱讀:

作者 : Waqas Anwar

翻譯 : 技術譯站

連結 : 英文原文


  1. https://www.ezzylearning.net/tutorial/a-beginners-guide-to-blazor-components A Beginner’s Guide to Blazor Components

  2. https://github.com/ezzylearning/BlazorComponentsDemo