Blazor 组件通讯

  Blazor 组件通讯示例,包含联级传参、双向绑定、服务传参 3 种方式。

Son.razor

 1 @using BlazorApp.Shared.Services;
 2 <div style="border:inherit;margin:inherit;background-color:ivory;">
 3     <h3>Son---@Value<input class="btn btn-info" type="button" value="自身+1,同时Self组件值+1" @onclick="ChangeValue" /></h3>
 4 
 5     <input type="text" @bind-value="@sunValue" />
 6     <input class="btn btn-info" type="button" value="控制Grand组件显示值" @onclick="ChangeGrandValue" />
 7 
 8     <h6>来自Parent组件 @ParentValue</h6>
 9     <input type="text" name="name" @bind-value="@Ceshi" />
10     <button @onclick="@Henfgu">给邻居发消息</button>
11 </div>
12 @code {
13     [Parameter]
14     public int? Value { get; set; } = 0;
15 
16     public string? Ceshi { get; set; }
17     [Inject]
18     public CommunicationToString? communicationToString { get; set; }
19 
20     private async Task ChangeValue()
21     {
22         Value++;
23         if (OnValueChanged.HasDelegate)
24         {
25             await OnValueChanged.InvokeAsync(Value);
26         }
27     }
28 
29     public string? sunValue { get; set; } = "Sun";
30 
31     /// <summary>
32     /// 获取Name为GrandValue的Grand组件
33     /// </summary>
34     [CascadingParameter(Name = "GrandValue")]
35     Grand? grand { get; set; }
36 
37     public async Task ChangeGrandValue()
38     {
39         await InvokeAsync(grand?.State_HasChanged(() => { grand.SetValue($"来自Sun组件 {sunValue}"); })!);
40     }
41 
42     public async Task Henfgu()
43     {
44         if (communicationToString != null)
45             communicationToString.Callback(Ceshi ?? "");
46 
47         await Task.CompletedTask;
48     }
49 
50     [CascadingParameter(Name = "ParentValue")]
51     string? ParentValue { get; set; }
52 
53     [Parameter]
54     public EventCallback<int?> OnValueChanged { get; set; }
55 }

 

Self.razor

 1 <div style="border:inherit;margin:inherit;background-color:#e4e4b5;">
 2     <h3>Self---@Value<input class="btn btn-info" type="button" value="+1" @onclick="OnInput" /></h3>
 3     
 4     <h6>来自Family组件 @family?._familyValue</h6>
 5     <Son Value="@Value" OnValueChanged="OnValueChanged" />
 6 </div>
 7 @code {
 8     [Parameter]
 9     public int? Value { get; set; } = 0;
10 
11     public void OnInput()
12     {
13         Value++;
14     }
15 
16     /// <summary>
17     /// 获取上级Name为FamilyValue的Family组件
18     /// </summary>
19     [CascadingParameter(Name = "FamilyValue")]
20     Family? family { get; set; }
21 
22     private void OnValueChanged(int? val)
23     {
24         Value = val;
25     }
26 }

 

Parent.razor

 1 <div style="border:inherit;margin:inherit;background-color:#f6df6e;">
 2     <h3>Parent---@Value<input class="btn btn-info" type="button" value="+1" @onclick="OnInput" /></h3>
 3     
 4     <input type="text" name="name" @bind-value="_parentValue" />
 5     <CascadingValue Value="@_parentValue" Name="ParentValue">
 6         <Self Value="@Value" />
 7     </CascadingValue>
 8 </div>
 9 @code {
10     [Parameter]
11     public int? Value { get; set; } = 0;
12 
13     private string _parentValue = "ParentValue";
14 
15 
16     public void OnInput()
17     {
18         Value++;
19     }
20 }

 

Grand.razor

 1 <div style="border:inherit;margin:1.5rem 5rem 5rem 5rem;background-color:forestgreen;">
 2     <h3>Grand---@Value<input class="btn btn-info" type="button" value="点击+1,同时改变Family的值" @onclick="OnInput" /></h3>
 3     双向绑定:<input type="text" name="name" value="@Value" @onchange="ChangeParentValue" />
 4     <h6>@value</h6>
 5     <CascadingValue Value="this" Name="GrandValue">
 6         <Parent Value="@Value" />
 7     </CascadingValue>
 8 </div>
 9 @code {
10     #region 双向绑定
11     [Parameter]
12     public int? Value { get; set; } = 0;
13 
14     /// <summary>
15     /// 命名方法 绑定的参数名+Changed
16     /// </summary>
17     [Parameter]
18     public EventCallback<int?> ValueChanged { get; set; }
19 
20     private async Task ChangeParentValue(ChangeEventArgs e)
21     {
22         if (e != null)
23         {
24             int.TryParse(e.Value!.ToString(), out var str);
25             await ValueChanged.InvokeAsync(str);
26         }
27     }
28     #endregion
29 
30     public async Task OnInput()
31     {
32         Value++;
33         await ValueChanged.InvokeAsync(Value);
34     }
35 
36     public string value { get; set; } = "Grand";
37 
38     public void SetValue(string value)
39     {
40         this.value = value;
41     }
42 
43     public Action<string> Test => (value) => { this.value = value; StateHasChanged(); };
44 
45     public Action? State_HasChanged(Action Execute) => Execute + StateHasChanged;
46 }

 

Family.razor

 1 @page "/family"
 2     <Neighbor />
 3     <Divider />
 4     <div style="border:solid;background-color:lightsteelblue;">
 5         <h3>Family---@Value<input class="btn btn-info" type="button" value="+1" @onclick="OnInput" /></h3>
 6 
 7         <input type="text" name="name" @bind-value="_familyValue" />
 8         <CascadingValue Value="this" Name="FamilyValue">
 9             <Grand @bind-Value="@Value" />
10         </CascadingValue>
11 
12     </div>
13     @code {
14         public int? Value { get; set; } = 0;
15 
16         public string _familyValue = "FamilyValue";
17 
18         public void OnInput()
19         {
20             Value++;
21         }
22 
23     }


Neighbor.razor

 1 @using BlazorApp.Shared.Services;
 2 <div style="border:solid;background-color:lightsteelblue;">
 3     <h3>Neighbor</h3>
 4     <h5>来至邻居家的: @Test</h5>
 5 </div>
 6 @code {
 7     public string? Test { get; set; }
 8 
 9 
10     [Inject]
11     public CommunicationToString? communicationToString { get; set; }
12 
13     protected override void OnInitialized()
14     {
15         base.OnInitialized();
16         //注册服务
17         communicationToString?.Register(Ceshi);
18     }
19 
20 
21     public Task Ceshi(string value)
22     {
23         Test = value;
24         StateHasChanged();
25         return Task.CompletedTask;
26     }
27 }

 

CommunicationToString.cs
1 namespace BlazorApp.Shared.Services
2 {
3     public class CommunicationToString : ServiceBase<string>
4     {
5 
6     }
7 }
 
ServiceBase.cs
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Threading.Tasks;
 4 
 5 namespace BlazorApp.Shared.Services
 6 {
 7     public abstract class ServiceBase<TOption>
 8     {
 9         private Func<TOption, Task>? _Callback { get; set; }
10 
11         private IDictionary<string, Func<TOption, Task>>? _Callbacks { get; set; } = new Dictionary<string, Func<TOption, Task>>();
12 
13         /// <summary>
14         /// 注册方法
15         /// </summary>
16         /// <param name="callback"></param>
17         internal void Register(Func<TOption, Task> callback) => _Callback = callback;
18 
19         /// <summary>
20         /// 回调方法
21         /// </summary>
22         /// <param name="option"></param>
23         /// <returns></returns>
24         public virtual void Callback(TOption option) => _Callback?.Invoke(option);
25 
26         /// <summary>
27         /// 注册方法到集合
28         /// </summary>
29         /// <param name="key"></param>
30         /// <param name="callback"></param>
31         internal void Register(string key, Func<TOption, Task> callback) => _Callbacks?.Add(key, callback);
32 
33         /// <summary>
34         /// 根据key值回调方法
35         /// </summary>
36         /// <param name="key"></param>
37         /// <param name="option"></param>
38         public virtual void Callback(string key, TOption option)
39         {
40             if (_Callbacks != null && _Callbacks.TryGetValue(key, out var callback))
41             {
42                 callback.Invoke(option);
43             }
44         }
45     }
46 }

 

posted @ 2022-04-17 22:57  一事冇诚  阅读(2071)  评论(1编辑  收藏  举报