初識 Blazor WebAssembly(Component)

1.元件生命週期

  1. SetParameterAsync 初始化前
  2. OnInitialized(Async) 初始化
  3. OnParametersSet(Async) 設定參數後
  4. OnAfterRender(Async) 渲染後

(1) SetParameterAsync(設定參數時,初始化之前

使用時機 : 第一次使用組件時,會先建立這個組件的執行個體

  1. 第一次要求轉譯組件時,將會觸發OnInitialized生命週期事件
  2. 執行屬性注入,這代表在轉譯樹狀結構中設定組件父系所提供的參數

(2) OnInitialized & OnInitializedAsync

使用時機 : SetParameterAsync進行初始化時被調用

在轉譯樹狀結構中從其父系收到其初始參數。

OnInitialized 同步

protected override void OnInitialized()
{
    ...
}

OnInitializedAsync 異步

protected override async Task OnInitializedAsync()
{
    await ...
}

(3) OnParametersSet & OnParametersSetAsync

OnParametersSet 則是在OnInitialized後執行一次,再來是每次只要Parameter有異動,就會執行一次

使用時機 :

  1. 當 OnInitialized/OnInitializedAsync 組件初始化執行結束後
  2. 組件加載之後如果參數發生改變時 ->可能被重複調用的第一對方法
  3. 父組件重新渲染並提供新參數時
  • 此時間點代表組件已經初始化完成

設定參數前 

public override async Task SetParametersAsync(ParameterView parameters)
{
    await ...

    await base.SetParametersAsync(parameters);
}

 設定參數後 同步

protected override void OnParametersSet()
{
    ...
}

 設定參數後 非同步

protected override async Task OnParametersSetAsync()
{
    await ...
}

(4) OnAfterRender & OnAfterRenderAsync(在Html都載入完畢後觸發 

使用時機 :

  1. 第一次轉譯組件實例
  2. 有事件產生時,每次轉譯組件之後叫用的方法。例如:點擊按鈕,參數更改時。
  3. 完成渲染後調用
  • 如果要使用第三方的 JavaScript 來存取 DOM,在此階段能正確取得

(5) 其他-ShouldRender 

使用時機 : 每次轉譯組件就會呼叫

  1. ShouldRender 方法將會用於傳回布爾值(預設回傳true),指出元件是否應該要進行轉譯處理動作。
  2. 如果想要避免使用者操作產生的渲染時,可以覆寫此方法來防止 UI 重新渲染,也就是可以確保渲染樹一定是從初始化產生的。
  3. Return false,會阻止重新計算組件的RenderTree,禁止UI刷新。就不會觸發OnAfterRender
protected override bool ShouldRender()
{
    return false;
}

 (6) 其他-產生渲染樹 BuildRenderTree

使用時機 : 如果ShouldRender 是true,就會將組件的內容呈現到畫面中

  1. 接收渲染輸出
  2. 此時間點代表組件已經完成渲染。此時 DOM 就已經畫好了

(7) 其他-Dispose 

使用時機 : 移除組件時觸發

@implements IDisposable
@code{
void IDisposable.Dispose()
    {
        Console.WriteLine(“組件銷毀");
    }
}

(8) 其他-StateHasChanged 狀態變更 

  • 一般來說,所有的 EventCallback 方法都會自動呼叫 StateHasChanged,來通知UI進行變更。
  • 但有時 Blazor 無法意識到狀態的變化,例如:何時被計時器觸發。這時需要手動調用 StateHasChanged 來通知 Blazor 某些參數已經被更改。表示向 Blazor渲染請求一個重新渲染,然後才觸發 OnAfterRender 和OnAfterRenderAsync

執行順序 

載入畫面時:

        1.SetParametersAsync->2.OnInitialized->3.OnParametersSetcount->4.OnAfterRender

執行點擊事件,改變變數內容

        執行click->5.ShouldRender->4.OnAfterRender

父組件重新渲染並提供新參數時

        執行click->5.ShouldRender->3.OnParametersSetAsync (子的)->4.OnAfterRender

 

點擊按鈕,父組件更改父組件屬性

        5.ShouldRender->4.OnAfterRender

點擊按鈕,父組件更改子組件屬性

        執行click->5.ShouldRender (父的)->1.SetParametersAsync (子的) -                         >3.OnParametersSetAsync (子的)->5.ShouldRender (子的)->4.OnAfterRender (父的)-               >4.OnAfterRender (子的)

點擊按鈕,狀態變更 StateHasChanged

        5.ShouldRender (子的)->4.OnAfterRender (子的)

點擊按鈕,頁面沒有變化

        5.ShouldRender (子的)->4.OnAfterRender (子的)

 

 2.Component Parameters 父傳參數給子

 父組件要傳遞資料給子組件的作法,是透過Parameter傳遞,子組件可以透過Paramter屬性取得資料。

注:

  • 子組件不可以跟父組件在同一層
  • 若組件之間namespace不同,要使用 @using

@using 補充 

 將@using指示詞新增至父組件或是_Imports.razor。即可讓資料夾中的 Components 組件可供使用,例:
@using BlazorSample.Components

將父組件FatherComponent.razor的data傳給子組件ChildComponent.razor 

 在父組件上設定按鈕上的字為send to child data

  • btnText="send to child data"
  • 子元件屬性="父組件變數"
  • [Parameter]為組件參數,會將資料傳遞至組件
  1. 子組件設置@變數,並透過透過[Parameter]將變數傳出
  2. 父組件透過@using使用子組件
  3. 父組件以HTML標籤方式引用子組件,並從父元件帶值給子組件

例:建立一個 ChildComponent.razor 和 ChildComponent.razor.cs文件

1. ChildComponent.razor

<Button Type="primary">@btnText</Button>

2.ChildComponent.razor.cs

using Microsoft.AspNetCore.Components;
namespace BlazorApp.Pages.Mybtn
{
    public partial class Mybtn
    {
        [Parameter]
        public string? btnText { get; set;}
        //透過[Parameter]將btnText傳出
    }
}

 建立一個FatherComponent.razor 和 FatherComponent.razor.cs文件

1.FatherComponent.razor

@page "/fathercomponent";

@using BlazorApp.Pages.Mybtn;
// 1.透過@using使用子組件(Pages裡面的Mybtn資料夾)

<h2>父傳參數給子</h2>

<div class="box">
    <Mybtn btnText="send to child data"></Mybtn>
    //2.使用子組件class名稱當作父組件html標籤
    //3.帶入參數 btnText="send to child data"
</div>

 2.FatherComponent.razor.cs

namespace BlazorApp.Pages.FatherComponent
{
    public partial class FatherComponnet
    {
    
    }
}

3.子組件發生事件時執行父組件的方法

  • 使用EventCallback。 父組件可以將回呼方法指派給子組件的 EventCallback
  • MouseEventArgs 鼠標的事件引數類型
  • e為自定義名稱的事件參數,例:
    可藉由e取得當下點擊的座標位置。
  • private string? message;
    
    private void MouseClick(MouseEventArgs e)
    {
        message = $"點擊的座標({e.ScreenX}:{e.ScreenY})";
    }

基礎Parameter應用 

 子組件(按鈕)發生點擊事件時,父組件執行方法,使畫面秀出點擊座標

  • OnClickCallback="@ShowMessage"
  • 子的屬性="@父的方法"
  • MouseEventArgs需要using Microsoft.AspNetCore.Components.Web

 定義一個子組件 Child.razor

(1)Child.razor

<Button @onclick="OnClickCallback">
    點擊
</Button>

(2) Child.razor.cs

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
//MouseEventArgs需要using  Microsoft.AspNetCore.Components.Web

namespace BlazorApp.Pages.Child
{
    public partial class Child
    {
        [Parameter]
        public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
        //1. 宣告OnClickCallback這個方法
        //1. 因為是click事件 所以使用相對應的 MouseEventArgs
        //2. 透過[Parameter]及EventCallback將方法傳出
    }
}

建立一個父組件Parent.razor

@page "/parent"
@using BlazorApp.Pages.Child;

<div class="box">
    <Child OnClickCallback="@ShowMessage">
    </Child>
    //1.這裡把父的方法 連結 子的屬性
    <p>@message</p>
</div>

 Parent.razor.cs

using Microsoft.AspNetCore.Components.Web;

namespace BlazorApp.Pages.Parent
{
    public partial class Parent
    {
        private string? message; 
        private void ShowMessage(MouseEventArgs e)
        {
            message = $"點擊的座標({e.ScreenX}:{e.ScreenY})";
        }
        //在父組件建立父的方法
    }
}

 2.循環子組件,根據子組件的序列值來操作

建立一個子組件 TodoChild.razor

 TodoChild.razor

<tr class="child">
    <td>@ItemName</td>
    <td><Button  @onclick="Delete" danger>Delete</Button></td>
<!--   定義Delete的方法  -->
</tr>

TodoChild.razor.cs 

using Microsoft.AspNetCore.Components;
namespace BlazorApp.Pages.TodoChild
{
    public partial class TodoChild
    {
        [Parameter]
        public string? ItemName { get; set; }
        //1.子組件宣告ItemName

        [Parameter]
        public int ItemIndex { get; set; }
        //2.子組件宣告ItemIndex
        //TodoList.Count -> 第 i 個 = ItemIndex

        [Parameter]
        public EventCallback<int> DeleteItem { get; set;}
        //3.宣告DeleteItem方法
        //3.透過EventCallback將方法傳出
        
        //4.定義方法內容
        void Delete()
        {
            DeleteItem.InvokeAsync(ItemIndex);
            //5.透過InvokeAsync(ItemIndex)調用父組件的回調方法
        }
    }
}

建立父組件TodoParent.razor

@using BlazorApp.pages.TodoChild
<div class="box">
    <h3>TodoList</h3>
    <input type="text" @bind="newTodoItem" />
    <!--   綁定使用者輸入的內容   -->
    <Button Type="primary" @onclick="Add">Add</Button>
    <!--   點擊按鈕觸發Add事件   -->

    <table>
        <tr>
            <th>待辦事項</th>
            <th>刪除</th>
        </tr>
        @for (int i = 0; i < TodoList.Count; i++)
        {
            <TodoChild ItemName="@TodoList[i]" ItemIndex="@i" DeleteItem="@DeleteCallback"/>
            <!--   引用子組件,並將DeleteCallback綁定子屬性DeleteItem   -->
        }
    </table>
</div>

 TodoParent.razor.cs

using Microsoft.AspNetCore.Components.Web;
namespace BlazorApp.Pages.TodoParent
{
    public partial class Parent
    {
        //=============================範例二
        private string? newTodoItem;
        //宣告newTodoItem (input綁定的值)
        private List<string> TodoList = new List<string>();
        //宣告TodoList

        protected override void OnInitialized()
        {
            TodoList = new List<string>()
            {
                "Buy Milk",
                "Buy Apple"
            };
            //宣告TodoList的物件內容
        }

        void Add()
        {
            if (!string.IsNullOrEmpty(newTodoItem))
            {
                TodoList.Add(newTodoItem);
                //TodoList 增加一個 input輸入的值
                newTodoItem = "";
            }
        }

        void DeleteCallback(int index)
        {       
            TodoList.RemoveAt(index);
        }
    }
}

 繼承子組件事件,父組件延伸事件內容

父組件要使用按鈕子組件,並加上自訂方法

  • 子元件建立一個點擊事件
  • 子元件透過[Parameter]EventCallback設定一個呼叫端的屬性
  • 點擊事件做兩件事
    1. 共同要做的事情
    2. 各父元件自定義的事情
      (使用InvokeAsync調用父組件的回調方法)
      await 呼叫端的屬性名稱.InvokeAsync(e);
  • 父元件透過HTML標籤將呼叫端的屬性綁定父元件方法A
  • 父元件A方法呼叫B方法

建立一個button的子組件

Mybtn.razor

<a class="@btnStyle" @onclick="Toggle">點擊會跳出父組件的Console</a>
@* //1.按鈕組件的按鈕內容為變數 *@
//Toggle function名稱

Mybtn.razor.cs 

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

// namespace 
namespace BlazorApp.Pages.Mybtn
{
    public partial class Mybtn
    {
        string btnStyle = "btn-blue";

        [Parameter]
        public EventCallback<MouseEventArgs> OnClickCallback { get; set;}
        //1.設定一個呼叫端的"屬性" -> OnClickCallback

        public async Task Toggle(MouseEventArgs e)
        //2.Toggle事件處理方法
        {
            btnStyle = btnStyle == "btn-blue" ? "btn-green" : "btn-blue";
            //3.子組件必要的function內容
            await OnClickCallback.InvokeAsync(e);
            //4.使用InvokeAsync調用父組件的回調方法
            //4.這裡可以調用父組件自定義的fucntion
            //4.InvokeAsync(Object)
        }
    }
}

父組件ParentBtn.razor

<div class="box">
    <h3>範例三 - 繼承子組件事件,父組件延伸事件內容</h3>
    <Mybtn OnClickCallback="@ConsoleWord"></Mybtn>
</div>

 ParentBtn.razor.cs

 

using Microsoft.AspNetCore.Components.Web;

namespace BlazorApp.Pages.ParentBtn
{
    public partial class ParentBtn
    {
        //=============================範例三
        void Aa()
        {       
            Console.WriteLine("parent的方法");
            //1.定義父組件自訂一的function內容
        }

        public void ConsoleWord(MouseEventArgs e)
        {
            //2.透過屬性綁定的Parent呼叫Aa()函式
            Aa();
        }
    }
}

 4.Cascading Paramater

  • CascadingValue 組件,包裝底下所有組件階層,並將單一值提供給其子樹狀結構中的所有組件。
  • 上層組件透過CascadingValue把值傳出
  • 下層[CascadingParamter]屬性接收傳來的值

傳遞多個參數,透過按鈕改變顏色及大小

 子層MainLayout.razor

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
    <CascadingValue Value="@state" > 
        <article class="content px-4">
            @Body
        </article>
    </CascadingValue>
    </main>
</div>

@code{
    State2 state = new State2();

    public class State2
    {
        public string? color { get; set; } = "pink";
        public string? size { get; set; } = "20px";
    }
}

父層ParentMenu.razor

@page "/ParentMenu"
@using Syncfusion.Blazor.Diagrams
@using BlazorApp.Pages

<h2>5-4 Cascading Parameter的運用</h2>

<div class="box">
    <p style="color:@state.color;font-size:@state.size">測試文字</p>
    <button style="background:@state.color;font-size:@state.size;color:white;" class="btn btn-sm">測試按鈕</button>
    <hr>
    <h4>選擇顏色:</h4>
    @foreach (var item in new string[] { "pink", "blue", "green" })
    {
        <div>
            <input type="radio" id="@item" name="colorRadio" value="@item" @onchange="ColorRadioSelection">
            <label for="@item">@item</label>
        </div>}
    <br />

    <h4>選擇文字大小:</h4>
    @foreach (var item in new string[] { "16px", "20px", "40px" })
    {
        <div class="custom-control custom-radio">
            <input type="radio" id="@item" name="sizeRadio" value="@item" @onchange="SizeRadioSelection">
            <label for="@item">@item</label>
        </div>
    }
</div>

@code {
    [CascadingParameter]
    public MainLayout.State2 state { get; set; } = null!;
        
    void ColorRadioSelection(ChangeEventArgs args)
    {
        state.color = args.Value.ToString();   
        Console.WriteLine(args.Value.ToString());
    }
    
    void SizeRadioSelection(ChangeEventArgs args)
    {
        state.size = args.Value.ToString();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值