前言

DynamicComponent 顧名思義就是動態元件,允許開發者依照邏輯去動態的轉譯需要的元件,這篇文章會介紹該如何使用

基本使用

建立四個 Component

  1. One.razor
1
2
3
4
5
<h3>One</h3>

@code {

}
  1. Two.razor
1
2
3
4
5
<h3>Two</h3>

@code {

}
  1. Three.razor
1
2
3
4
5
<h3>Three</h3>

@code {

}
  1. DynamicComponentExample.razor
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@page "/DynamicComponentExample"
<h3>DynamicComponentExample</h3>
<select @onchange="OnDropdownChange">
    <option value="">Select a value</option>
    <option value="@nameof(One)">第一個元件</option>
    <option value="@nameof(Two)">第二個元件</option>
    <option value="@nameof(Three)">第三個元件</option>
</select>

@if (selectedType is not null)
{
    <div class="border border-primary my-1 p-1">
        <DynamicComponent Type="@selectedType" />
    </div>
}
@code {
    private Type? selectedType;

    private void OnDropdownChange(ChangeEventArgs e)
    {
        selectedType = e.Value?.ToString()?.Length > 0 ? Type.GetType($"BlazorApp1.Pages.{e.Value}") : null;
    }
}

Type.GetType($“BlazorApp1.Pages.{e.Value}”) 內的 Type.GetType 需要填入專案的命名空間

完成後的效果如下,會按照選取的類型去動態轉譯元件

動態轉譯需要參數的元件

和上面的步驟相同只有兩個地方做異動

  1. One.razor 加入一個由外部傳入的參數
1
2
3
4
5
6
<h3>One</h3>
<p>@Content</p>
@code {
    [Parameter]
    public string Content { get; set; }
}
  1. DynamicComponentExample.razor 動態轉譯時提供參數,元件參數需要以 IDictionary<string, object> string 是參數名稱 object 則是參數的值
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@page "/DynamicComponentExample"
<h3>DynamicComponentExample</h3>
<select @onchange="OnDropdownChange">
    <option value="">Select a value</option>
    <option value="@nameof(One)">第一個元件</option>
    <option value="@nameof(Two)">第二個元件</option>
    <option value="@nameof(Three)">第三個元件</option>
</select>

@if (selectedType is not null)
{
    <div class="border border-primary my-1 p-1">
        <DynamicComponent Type="@selectedType"  Parameters="@components[selectedType.Name].Parameters" />
    </div>
}
@code {
    private Type? selectedType;

    public class ComponentMetadata
    {
        public string? Name { get; set; }
        public Dictionary<string, object> Parameters { get; set; } = new();
    }

    private Dictionary<string, ComponentMetadata> components = new()
    {
        {
            nameof(One), new ComponentMetadata() { Parameters = new Dictionary<string, object> { { "Content", "我是參數內容" } } }
        },
        {
            nameof(Two), new ComponentMetadata()
        },
        {
            nameof(Three), new ComponentMetadata()
        }
    };

    private void OnDropdownChange(ChangeEventArgs e)
    {
        selectedType = e.Value?.ToString()?.Length > 0 ? Type.GetType($"BlazorApp1.Pages.{e.Value}") : null;
    }

}

## 動態轉譯有實作事件回呼的元件

最後來展示有實作 EventCallback 的元件

  1. One.razor
1
2
3
4
5
6
7
8
<h3>One</h3>
<button @onclick="OnClickCallback">
    按我
</button>
@code {
    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
  1. DynamicComponentExample.razor
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@page "/DynamicComponentExample"
<h3>DynamicComponentExample</h3>
<select @onchange="OnDropdownChange">
    <option value="">Select a value</option>
    <option value="@nameof(One)">第一個元件</option>
    <option value="@nameof(Two)">第二個元件</option>
    <option value="@nameof(Three)">第三個元件</option>
</select>
<p>@message</p>

@if (selectedType is not null)
{
    <div class="border border-primary my-1 p-1">
        <DynamicComponent Type="@selectedType" Parameters="@Components[selectedType.Name].Parameters" />
    </div>
}
@code {
    private Type? selectedType;
    private void CallbackMessage(MouseEventArgs e) => message = $"{DateTime.Now}";
    private string? message;

    public class ComponentMetadata
    {
        public string? Name { get; set; }
        public Dictionary<string, object> Parameters { get; set; } = new();
    }

    private Dictionary<string, ComponentMetadata> Components => new Dictionary<string, ComponentMetadata>()
    {
        {
            nameof(One),
            new ComponentMetadata
            {
                Name = nameof(One),
                Parameters =
                    new Dictionary<string, object>
                    {
                        {
                            "OnClickCallback",
                            EventCallback.Factory.Create<MouseEventArgs>(
                                this, CallbackMessage)
                        }
                    }
            }
        },
        {
            nameof(Two),new ComponentMetadata()
        },
        {
            nameof(Three),new ComponentMetadata()
        }
    };

    private void OnDropdownChange(ChangeEventArgs e)
    {
        selectedType = e.Value?.ToString()?.Length > 0 ? Type.GetType($"BlazorApp1.Pages.{e.Value}") : null;
    }

}

選擇第一個元件 點選按我按鈕

小結

在這一篇文章中,我們學習了怎麼使用動態轉譯元件,並且處理有參數的元件以及處理有參數是事件回呼的原件,有了動態轉譯可以讓 Blazor 開發上有更多的彈性