2019年12月12日 星期四

ASP.NET Core Blazor 單向與雙向資料綁定

ASP.NET Core Blazor 單向與雙向資料綁定

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。


幾乎所有的 GUI 開發框架,都需要具備有資料綁定 Data Binding 這樣的功能,若正在使用的開發框架 Framework 沒有提供類似這樣的功能,則十分建議可以不用再繼續使用了;而當然,對於強大的 Blazor 開發框架,也是具有這樣的特性,因此,將會透過這篇文章中的兩個頁面範例,進行展示出來這樣好用的功能是要如何來使用。
在這篇文章所提到的專案原始碼,可以從 GitHub 下載

單向資料綁定 Oneway Data Binding

在 Blazor 中所謂的單向資料綁定,指的是當 .NET CLR 的物件有異動的時候,將會進行更新到 UI 上的,對於像是在 MVVM Model View ViewModel 設計模式下,對於單向資料綁定可以使用於當 ViewModel 內的屬性有異動的時候,將會更新 View 上的顯示內容,或者是僅有當 View 上的顯示內容有異動的時候,才會更新到 ViewModel 內的屬性上,反之則不會成立。
想要進行這樣的專案開發練習,可以參考底下的操作步驟
  • 打開 Visual Studio 2019 開發工具
  • 當 [Visual Studio 2019] 對話窗出現之後,點選右下方的 [建立新的專案] 按鈕
  • 在 [建立新專案] 對話窗內,請找出 [Blazor 應用程式] 這個專案開發範本,並且點選這個專案開發範本
  • 請點選右下角 [下一步] 按鈕
  • 出現 [設定新的專案] 對話窗,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱],完成後,請點選右下角 [建立] 按鈕
    在這個範例程式碼中,將會建立一個 BlazorDataBinding 專案名稱
  • 此時將會看到 [建立新的 Blazor 應用程式] 對話窗,這裡可以根據當時開發專案的需要,自行決定是否有調整 Blazor 專案的其他特性,若無,請點選右下角的 [建立] 按鈕
  • 此時,這個 Blazor 專案已經建立完成
現在可以開始來建立一個單向資料綁定的頁面,練習如何設計單向資料綁定的程式設計方法:
  • 滑鼠右擊 [Pages] 資料夾,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Blazor 元件] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Blazor 元件的名稱
    這裡將會建立一個 OnewayBinding 新 Blazor 元件
    Blazor 元件檔案名稱都會使用 .razor 作為其副檔名
  • 最後,點選右下角的 [新增] 按鈕
請將底下的 Blazor 頁面之標記與程式碼,寫入到這個檔案內
@page "/OnewayBinding"
@using System.Threading
@using System.Threading.Tasks

<h3>單向資料綁定</h3>

<div>
    @Message
</div>
<buttn class="btn btn-outline-primary"
       @onclick="Start">開始動作</buttn>
<div class="@background" style="height:300px;border:none">
    @background
</div>

@code {
    string Message = "尚未接收到任何訊息";
    string background = "bg-transparent";
    int index = 0;
    CancellationTokenSource cts = new CancellationTokenSource();
    CancellationToken token;

    void Start()
    {
        Message = "已經接收到要開始動作指令了";
    }

    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            CancellationToken token = cts.Token;
            ShowCycle(token);
        }
        return Task.FromResult(0);
    }
    async Task ShowCycle(CancellationToken token)
    {
        while(true)
        {
            ShowColor();
            StateHasChanged();
            await Task.Delay(900);
            if(token.IsCancellationRequested)
            {
                break;
            }
        }
    }
    void ShowColor()
    {
        switch (index)
        {
            case 0:
                background = "bg-primary";
                break;
            case 1:
                background = "bg-secondary";
                break;
            case 2:
                background = "bg-success ";
                break;
            case 3:
                background = "bg-danger";
                break;
            case 4:
                background = "bg-warning";
                break;
            case 5:
                background = "bg-info";
                break;
            case 6:
                background = "bg-light";
                break;
            case 7:
                background = "bg-dark";
                break;
            case 8:
                background = "bg-white";
                break;
            default:
                break;
        }
        index++;
        if (index > 8) index = 0;
    }
}
在這個頁面中,將會宣告一個 Message 變數,並且透過 Razor 語法,將這個變數顯示在 HTML 標記內,如同這樣 <div>@Message</div> ,如此,當 Message 變數值有異動的時候,就會變更 HTML 上面的內容,也就達成了更新網頁內容的目的;這一切的效果都會透過 Blazor 內建的資料綁定機制來完成,而這裡所使用的技巧就是單向 Oneway Data Binding 資料綁定技術,最重要的是,所有的過程,開發者都不再需要透過 JavaScript 或者相關 JS 開發框架 Angular / React / Vue 等等來達成。
為了要能夠呈現出當 Message 變數有變動,網頁會如何顯示,這裡將會標記一個 <button> 標記,並且使用 @onclick="Start" 這樣的語法來宣告,當這個按鈕被觸發的時候,將會執行該頁面中的 Start 方法,在 Start() 方法內,將會執行 Message = "已經接收到要開始動作指令了"; 敘述,也就是說 Message 這個變數值已經變動了,此時,可以觀察網頁畫面,就會看到這個頁面上的文字,會從 [尚未接收到任何訊息] 轉變成為 [尚未接收到任何訊息] ,這一切發生的效果是不是很神奇呀。
另外,在這個頁面中,也會使用到 Blazor Componet Lifecycle 元件生命週期的事件:OnAfterRenderAsync ,該事件會當整個網頁已經顯示在瀏覽器上的時候,會被觸發執行,在這個事件委派方法內,將會執行 ShowCycle() 方法,這是一個 Fire and Forget 射後不理 的非同步工作方法。
在 ShowCycle 方法內,每隔 0.9 秒的時間,變更 background 變數的數值,這個變數將會綁定到網頁上的 div 標籤的 class 屬性上,也就是將這個變數字串內容,設定為各種 Bootstrap 4 的背景顏色類別宣告,這樣將會達成每隔 0.9 秒的時間,就會更換這個 div 標記內的背景顏色效果;因為該 div 的 class 宣告值有異動,透過 Blazor 的重新渲染機制,將會更新網頁中 DOM 內容,造成顏色有變化效果。
不過,要特別注意的是,當 background 字串值變動之後,將會需要呼叫 StateHasChanged() 這個方法,該方法將會 通知組件其狀態已更改。如果適用,這將導致重新渲染組件;也就是說,若沒有加入這個方法呼叫,每隔 0.9 秒將不會有任何背景顏色的變化出來。
底下將會是執行後的螢幕畫面
一開始顯示網頁的時候,在按鈕的上方文字會顯示為 : 尚未接收到任何訊息,而在最下方的區塊,將會不斷地變換背景顏色。
現在,可以點選螢幕上的按鈕,此時該按鈕的上方文字將會顯示為 : 已經接收到要開始動作指令了
這一切的成果,都將會透過 Blazor 單向資料綁定來做到。

雙向資料綁定 Twoway Data Binding

現在,要來體驗 雙向資料綁定 Twoway Data Binding,在 Blazor 中所謂的雙向資料綁定,指的是當 .NET CLR 的物件有異動的時候,將會進行更新到 UI 上,而當網頁上綁定的值有變動的時候,例如,使用者在該 UI 上輸入了任何資料,此時,將會更新到 .NET CLR 的變數上,反之亦然,也就是當 .NET CLR 變數有變動的時候,也會更新到 HTML 網頁上 DOM 內容。
現在可以開始來建立一個雙向資料綁定的頁面,練習如何設計雙向資料綁定的程式設計方法:
  • 滑鼠右擊 [Pages] 資料夾,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Blazor 元件] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Blazor 元件的名稱
    這裡將會建立一個 TwowayBinding 新 Blazor 元件
    Blazor 元件檔案名稱都會使用 .razor 作為其副檔名
  • 最後,點選右下角的 [新增] 按鈕
請將底下的 Blazor 頁面之標記與程式碼,寫入到這個檔案內
@page "/TwowayBinding"

<h3>雙向資料綁定</h3>

<input type="text" value="@Message1" />
<div>@Message1</div>
<input type="text" @bind="Message2" />
<div>@Message2</div>
<input type="range" class="form-control-range" max="8" min="0" step="1"
       @bind="Index" @bind:event="oninput" />
<div class="@background" style="height:200px;border:none">
    @background
</div>
@code {
    string Message1 = "Message1";
    string Message2 = "Message2";
    string background = "bg-transparent";
    private int index;

    public int Index
    {
        get { return index; }
        set
        {
            index = value;
            ShowColor();
        }
    }

    void ShowColor()
    {
        switch (Index)
        {
            case 0:
                background = "bg-primary";
                break;
            case 1:
                background = "bg-secondary";
                break;
            case 2:
                background = "bg-success ";
                break;
            case 3:
                background = "bg-danger";
                break;
            case 4:
                background = "bg-warning";
                break;
            case 5:
                background = "bg-info";
                break;
            case 6:
                background = "bg-light";
                break;
            case 7:
                background = "bg-dark";
                break;
            case 8:
                background = "bg-white";
                break;
            default:
                break;
        }
    }
}
在這個頁面中,將會同樣的會展現兩個功能特色,在上半部會有兩個 input 文字輸入盒,而在這兩個 input 文字輸入盒的下方,將會有 div 標籤,將綁定在 input 文字輸入盒內的文字內容,顯示在網頁上;在這兩個 input 宣告標記中,可以看到使用了不同的宣告語法,在前者將會把 HTML 內的這個 input 標記之 value 屬性,也就是使用這樣的 value="@Message1" 宣告語法,綁定到 .NET CLR 的 Message1 這個變數內,而這樣的做法將會是屬於單向資料綁定,也就是說,若使用者在網頁上的第一個 input 上輸入任何文字,將不會更新到 Message1 這個變數上,也就是對於 <div>@Message1</div> 標記而言,顯示的內容都是相同的,因為 Blazor 不會透過 DOM 內容,來變更這個 div 內的文字內容。
對於第二個 input 標記而言,將會使用了 @bind="Message2" 這樣的宣告語法,這是一個雙向資料綁定的宣告語法,也就是說,當使用者在第二個 input 文字輸入盒,輸入了任何文字,將會造成下方的 <div>@Message2</div> 標記也會更新,因為,當使用者變更 input 輸入文字內容,就會同時更新 .NET CLR Message2 物件內的值,而當這個 Message2 的物件值變動後,就會透過資料綁定機制,更新了 DOM 內 <div>@Message2</div> 標記內容,如此,將會造成可以顯示出使用者最新輸入的文字內容了。
在最下方的 input 標記,宣告型別為 type="range" 來形成一個 滑動桿 輸入控制項, 這裡宣告了 @bind="Index" 語法,讓滑動桿輸入的值,可以使用雙向資料綁定的方式,綁定到 .NET CLR 內的 Index 變數內,另外,為了要能夠做到當滑動桿的值又變化的時候,可以立即觸發雙向資料綁定的效果,而不再使用滑鼠點擊到網頁的其他地方,來觸發雙向資料綁定的動作,因此,在這裡將會使用 @bind:event="oninput" 這樣的宣告方式,設定了只要滑動桿的值有變化的時候,立即會觸發雙向資料綁定動作。
當因為雙向資料綁定機制,導致 .NET CLR 的 Index 變數有變動的時候,將會使得該屬性 C# Property 之設定存取子被執行,這裡將會把 index 這個支援欄位的變數值進行更新,接著,將會呼叫 ShowColor 方法,如此,將會造成最下方的 div 標記的背景顏色有所變更。
這裡可以觀察到,這裡將沒有呼叫 StateHasChanged() 這個方法,但是,同樣的會進行更新 DOM 的內容,也就是會變更 HTML 顯示內容。
底下將會是執行後的螢幕畫面
當一開始執行的時候,最上方的兩個文字輸入盒,都會顯示預設的 .NET CLR 變數值,這是因為,雙方都具有單向綁定的特性。
現在,在第一個文字輸入盒內,輸入任何文字之後,發現到其下方的 div 標記內的文字,沒有同步更新,這是因為第一個 input 使用的是單向資料綁定的宣告語法。
對於第二個 input 文字輸入盒,在此輸入任何文字,便可以看到底下的 div 區塊內的文字,有同步更新,這是因為這裡使用了雙向資料綁定的宣告語法。
接著請使用滑鼠滑動滑動桿,便可以看到滑動桿的下方 div 區塊的背景顏色,會不斷的變化顏色




沒有留言:

張貼留言