1. 程式人生 > 其它 >Blazor 資料繫結開發指南

Blazor 資料繫結開發指南

翻譯自 Waqas Anwar 2021年3月21日的文章 《A Developer’s Guide to Blazor Data Binding》 [1]

現如今,大多數 Web 應用程式要麼是在頁面上顯示某種資料,要麼是使用表單從使用者那裡收集資料。這意味著每個 SPA 框架都必須支援資料繫結,以便開發者可以將資料與 labelform 控制元件等元素進行繫結。Blazor 元件內建了對資料繫結的支援,還使用了多種技術來同時支援單向和雙向資料繫結。在本教程中,我將通過一個簡單的卡片設計器示例來介紹 Blazor 資料繫結功能的基礎知識,在該示例中,使用者能夠檢視其卡片設計的實時更新情況。

下載原始碼[2]

單向繫結

在單向資料繫結中,資料沿一個方向傳遞。應用程式程式碼更新值以響應某些事件或使用者操作,當值更新時,相應的 UI 也會動態更新。單向資料繫結中,不允許使用者直接更改值。在 Blazor 中,我們通常使用 @ 符號後跟屬性、欄位,甚至是一個方法來實現單向資料繫結。例如,如果您的程式碼中有一個 Title 屬性,並且您想將它與一個 h1 元素繫結,那麼您可以編寫類似以下程式碼段的程式碼。

<h1>@TItle</h1>

現在,要更新上述程式碼中的 Title,您可以使用一個簡單的按鈕 onclick 事件,呼叫程式碼中的 UpdateTitle

方法來更新 Title 屬性的值。因為一旦使用者點選按鈕,更新的值便自動從程式碼傳遞到使用者介面,所以 h1 元素的文字將會自動更新。

<button @onclick="UpdateTitle">Update Title</button>
 
@code{
    public string Title { get; set; } = "Hello";
 
    private void UpdateTitle()
    {
        Title = "Hello, Blazor!";
    }
}

雙向繫結

在雙向資料繫結中,資料是雙向流動的。通常,使用者在前端以某種形式更新某個值,該值在後端程式碼中自動更新,然後這個新值再傳遞到 UI 並更新繫結到該值的所有元素。在 Blazor 中,可以使用 @bind

特性實現雙向資料繫結,該特效能夠以多種方式使用。下面的簡單示例演示了 @bind 特性的基本用法,在這個示例中我們使用 @bind=Property 語法將 Title 屬性與 input 元素進行繫結。

<h1>@Title</h1>
 
<input @bind="Title" />
 
@code {
    public string Title { get; set; } = "Blazor";
}

我們還可以將某一屬性繫結到特定的事件,以便僅在特定的事件觸發時才更新該屬性的值。繫結到特定事件的語法是 @bind:event="EVENT NAME"。例如,在下面的程式碼段中,我希望僅在使用者將焦點從輸入框移開時才改變 Title 屬性。

<h1>@Title</h1>
 
<input @bind="Title" @bind:event="onchange" />
 
@code {
    public string Title { get; set; } = "Blazor";
}

現在我們已經掌握了 Blazor 資料繫結的基礎知識,那麼,在接下來的教程中,我將向您展示一些使用資料繫結的真實示例。在我們開始之前,請確保您已熟悉了建立和使用 Blazor 元件。如果您不瞭解如何建立 Blazor 應用程式或元件,我建議您閱讀我之前的文章 Blazor 元件入門指南

入門例項

在 Visual Studio 2019 中建立一個 Blazor Server 應用,並在 Pages 資料夾中新增一個新的 Blazor 元件 CardDesigner.razor。 我們想要構建一個簡單的卡片設計器頁面,允許使用者同時設計和預覽卡片。 讓我們在新建元件的 razor 檢視中新增以下 HTML 標記。

CardDesigner.razor

@page "/"
 
<h1>Card Designer (Blazor Data Binding)</h1> 
 
<div class="container">
    <div class="row">
        <div class="col-8">
            <h3>Design</h3>
            <form>
                <div class="form-group">
                    <label for="Heading">Heading</label>
                    <input type="text" class="form-control" id="Heading">
                </div>
                <div class="form-group">
                    <label for="Description">Description</label>
                    <textarea class="form-control" id="Description" rows="4"></textarea>
                </div>              
                <button class="btn btn-secondary mb-2">Reset</button>
            </form>
        </div>
        <div class="col-4">
            <h3>Preview</h3>
            <div class="card bg-light w-100">
                <div class="card-header">
                    Heading
                </div>
                <div class="card-body">
                    <p class="card-text">
                        Description
                    </p>
                </div> 
            </div>
        </div>
    </div>
</div>

為了確保我們的卡片設計器看起來賞心悅目,您還需要在 wwwroot/css/site.css 檔案中新增一些基本的 CSS 樣式。

site.css

.container {
    margin: 15px;
    padding: 0px;
}
.col-8, .col-4 {
    border: 1px solid #dadada;
    padding: 10px;
}
h1 {
    font-size: 22px;
    font-weight: bold;
    margin-bottom: 30px;
    margin-top: 20px;
}
h3 {
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 25px;
}

執行該應用程式,您應該能看到類似以下內容的頁面。左手邊是設計部分,允許使用者設定卡片的 HeadingDescription,右手邊顯示卡片預覽。還有一個 Reset 按鈕,可以將表單重置為預設值。

讓我們為卡片設計器的實現邏輯建立一個單獨的程式碼隱藏部分類(partial class)。該類有兩個簡單的帶有預設值的屬性 HeadingDescription。還有一個 ResetCard 方法,當用戶點選 Reset 按鈕時會呼叫此方法,將兩個屬性重置為其預設值。

CardDesigner.razor.cs

public partial class CardDesigner
{
    public string Heading { get; set; } = "Heading";
    public string Description { get; set; } = "Description";
 
    public void ResetCard(MouseEventArgs e)
    {
        Heading = "Heading";
        Description = "Description";
    }
}

單向繫結例項

現在,我們已為檢視 Blazor 資料繫結功能的實際應用做好了準備。讓我們先從單向資料繫結開始。稍微更新一下上面的 <form> 程式碼,並使用 @ 符號和屬性名新增單向繫結。我將 inputtextarea 元素的 value 特性(attribute)繫結到 HeadingDescription 屬性(property),然後新增 @onchange 事件,使用 Lambda 表示式語法更改 Heading 屬性。還將 ResetCard 方法附加到了 Reset 按鈕的 onclick 事件。

CardDesigner.razor

<form>
   <div class="form-group">
      <label for="Heading">Heading</label>
      <input type="text" class="form-control" id="Heading" value="@Heading"
         @onchange="@(e => { Heading = e.Value.ToString(); })">
   </div>
   <div class="form-group">
      <label for="Description">Description</label>
      <textarea class="form-control" id="Description" rows="4"
         @onchange="@(e => { Description = e.Value.ToString(); })" value="@Description"></textarea>
   </div>
   <button type="button" class="btn btn-secondary mb-2" @onclick="ResetCard">Reset</button>
</form>

我們還需要使用單向資料繫結更新預覽部分的卡片,以便每次程式碼中的 HeadingDescription 更新時,預覽部分都會自動在卡片上渲染更新後的值。

CardDesigner.razor

<div class="card text-white w-100 @SelectedStyleCssClass">
   <div class="card-header">
      @Heading
   </div>
   <div class="card-body">
      <p class="card-text">
         @Description
      </p>
   </div>
</div>

現在,如果您執行應用程式,您將會看到類似於下面的輸出。嘗試在設計區輸入標題和描述,您會注意到,當您將焦點從輸入框移開時,預覽區會立即自動更新。

如果您不喜歡在 HTML 中使用 Lambda 表示式,您還可以在程式碼中定義 UpdateHeadingUpdateDescription 方法,然後將這些方法與 @onchange 事件關聯起來。

CardDesigner.razor

<form>
   <div class="form-group">
      <label for="Heading">Heading</label>
      <input type="text" class="form-control" id="Heading" value="@Heading"
         @onchange="UpdateHeading">
   </div>
   <div class="form-group">
      <label for="Description">Description</label>
      <textarea class="form-control" id="Description" rows="4"
         value="@Description"
         @onchange="UpdateDescription"></textarea>
   </div>
   <button type="button" class="btn btn-secondary mb-2" @onclick="ResetCard">Reset</button>
</form>

CardDesigner.razor.cs

public partial class CardDesigner
{
    public string Heading { get; set; } = "Heading";
    public string Description { get; set; } = "Description";
 
    public void ResetCard(MouseEventArgs args)
    {
        Heading = "Heading";
        Description = "Description";
    }
 
    public void UpdateHeading(ChangeEventArgs e)
    {
        Heading = e.Value.ToString();
    }
 
    public void UpdateDescription(ChangeEventArgs e)
    {
        Description = e.Value.ToString();
    }
}

雙向繫結例項

截至目前,我們僅在應用程式中使用了單向繫結,因為 HeadingDescription 屬性的值是在我們的程式碼中更新的,而且我們的程式碼只在使用者將焦點從表單控制元件移開時才執行。讓我們更新一下示例的程式碼,看看如何在該示例中使用雙向資料繫結。使用 @bind 特性將 HeadingDescription 屬性與表單控制元件繫結。我還希望當用戶開始在表單控制元件中打字時立即更新卡片預覽。為此,請將 @bind:event="oninput" 新增到了 inputtextarea 控制元件。

CardDesigner.razor

<form>
   <div class="form-group">
      <label for="Heading">Heading</label>
      <input type="text" class="form-control" id="Heading" @bind="Heading" @bind:event="oninput">
   </div>
   <div class="form-group">
      <label for="Description">Description</label>
      <textarea class="form-control" id="Description" rows="4" @bind="Description" @bind:event="oninput"></textarea>
   </div>
   <button type="button" class="btn btn-secondary mb-2" @onclick="ResetCard">Reset</button>
</form>

現在,雙向繫結已經設定好了,因此我們不再需要手動更新屬性,這樣我們就可以將 UpdateHeadingUpdateDescription 方法從程式碼中刪除。

CardDesigner.razor.cs

public partial class CardDesigner
{
    public string Heading { get; set; } = "Heading";
    public string Description { get; set; } = "Description";
 
    public void ResetCard(MouseEventArgs args)
    {
        Heading = "Heading";
        Description = "Description";
    }
}

再次執行應用程式並在設計表單中輸入標題和描述,看下卡片預覽是如何自動更新的。

讓我們進一步擴充套件我們的示例,在設計區引入一個下拉列表控制元件。該下拉列表將顯示不同的卡片樣式,使用者能夠使用雙向資料繫結即時地選擇和應用任一卡片樣式。讓我們在 Data 資料夾中新增以下 StyleInfo 類。

StyleInfo.cs

public class StyleInfo
{
    public string Name { get; set; }
    public string CssClass { get; set; }
}

讓我們在 CardDesigner.razor.cs 檔案中再新增兩個屬性來儲存可用卡片樣式的列表,並存儲所選樣式的引用。我們在名為 OnInitialized 的元件初始化方法中初始化 Styles 屬性。在從父元件接收到初始化引數後,元件會進行初始化,初始化完成時將呼叫 OnInitialized 方法。

CardDesigner.razor.cs

public partial class CardDesigner
{
    public string Heading { get; set; } = "Heading";
    public string Description { get; set; } = "Description";
    public List<StyleInfo> Styles { get; set; }
    public string SelectedStyleCssClass { get; set; }
 
    protected override void OnInitialized()
    {
        Styles = new List<StyleInfo>()
        {
            new StyleInfo() { Name = "Primary", CssClass = "bg-primary" },
            new StyleInfo() { Name = "Secondary", CssClass = "bg-secondary" },
            new StyleInfo() { Name = "Success", CssClass = "bg-success" } 
        };
 
        SelectedStyleCssClass = "bg-primary";
    }
 
    public void ResetCard(MouseEventArgs args)
    {
        Heading = "Heading";
        Description = "Description";
    }
}

最後,我們需要在 CardDesigner.razor 檔案中新增一個 HTML select 元素。我們執行一個簡單的 @foreach 迴圈來迭代 Styles 屬性,並在迴圈中建立 <option> 元素。每個 <option> 元素的 value 特性使用 CssClass 屬性值呈現,每個 <option> 元素的文字使用 Name 屬性值呈現。

CardDesigner.razor

<div class="form-group">
   <label for="Style">Style</label>
   <select class="form-control" id="Style" @bind="SelectedStyleCssClass" @bind:event="onchange">
      @foreach (var style in Styles)
      {
      <option value="@style.CssClass">@style.Name</option>
      }
   </select>
</div>

在上面的程式碼片段中,我們使用 @bind 特性將 SelectedStyleCssClass 屬性與 select 元素繫結,並指定使用 selectonchange 事件,以便每次使用者從下拉列表中選擇一個選項時,卡片樣式自動更新。

現在,如果您執行專案,將會看到下拉列表中填充的樣式,並且選中的樣式會應用到預覽部分的卡片。

右鍵點選 select 元素並選擇 檢查(Inspect) 選單選項,可以檢視 option 是如何渲染在 HTML 中的,以及每個 optionvalue 是如何包含我們在程式碼中初始化的 CssClass 屬性的。

試試從下拉列表中選擇不同的樣式,卡片預覽會立即更新。

總結

在本教程中,我介紹了 Blazor 資料繫結的基礎知識。我們學習瞭如何使用單向和雙向資料繫結功能,以及如何使用資料繫結更新值。我們還學習瞭如何利用不同的事件來指定何時更新值。在 Blazor 中還有一些更高階的資料繫結概念,我將盡最大的努力就這個主題再寫幾篇文章。


相關閱讀:

作者 : Waqas Anwar
翻譯 : 技術譯站
連結 : 英文原文


  1. https://www.ezzylearning.net/tutorial/a-developers-guide-to-blazor-data-binding A Developer’s Guide to Blazor Data Binding ↩︎

  2. https://github.com/ezzylearning/BlazorDataBindingDemo 下載原始碼 ↩︎

© 轉載請標明出處 https://www.cnblogs.com/ittranslator

不做標題黨,只分享技術乾貨

公眾號『技術譯站』,歡迎掃碼關注