我有一个带有子组件的父组件
<h3>Parent component</h3>
<Child />
孩子有孙子
<h3>Child component</h3>
<Grandchild @bind-SelectedVariant="_selectedVariant" />
<h4>Costs: @GetCosts()</h4>
GetCosts()
取决于 _selectedVariant
。
孙子是
<h3>Grandchild component</h3>
<input type="checkbox" @onclick="(e) => ToggleCheckboxAsync("Variant 1")" />
@code {
[Parameter] public string SelectedVariant { get; set; } = "";
[Parameter] public EventCallback<string> SelectedVariantChanged { get; set; }
private async Task OnSelectedVariantChange(string selectedVariant) => await SelectedVariantChanged.InvokeAsync(selectedVariant);
private async Task ToggleCheckboxAsync(string clickedVariantName)
{
await OnSelectedVariantChange(clickedVariantName);
StateHasChanged();
}
}
这个效果很好。当我切换复选框时,显示的成本会更新。 (仅在选中复选框时,因为本示例中未实现取消选中。)
我发现,我需要父组件中的成本。所以,我的第一次尝试是通过 EventCallback 添加另一个绑定:
<h3>Child component</h3>
<Grandchild @bind-SelectedVariant="_selectedVariant" />
<h4>Costs: @GetCosts()</h4>
@code {
[Parameter, EditorRequired] public int Costs { get; set; } = -1;
[Parameter] public EventCallback<int> CostsChanged { get; set; }
private async Task OnCostsChange() => await CostsChanged.InvokeAsync(Costs);
}
和
<h3>Parent component</h3>
<Child @bind-Costs="_costs" />
但是我如何触发
OnCostsChange()
?使用 OnSelectedVariantChange()
很容易,因为这只是复选框的单击事件。
由于 Child 组件中没有触发器,我认为
OnCostsChange()
没有任何意义,Costs
& EventCallback<int> CostsChanged
属性足以进行双向绑定。有关更多详细信息,您可以查看此 document
如果你想从父组件中调用子组件中的方法,你可以尝试:
<Child @bind-Costs="_costs" @ref="Child"/>
<button @onclick="TriggerChildMethod">Button</button>
@code{
public int _costs;
private Child Child { get; set; }
public async Task TriggerChildMethod()
{
await Child.SomeMethod();
}
}
在子组件中:
public async Task SomeMethod() {......}
我认为你可能有点过于复杂化了。如果您打算将值从父级传递给子级,则只需要进行双向绑定。如果孩子执行一些逻辑来得出该值,则只需使用回调即可。
这是我的
Grandchild
。我猜现实中有多种变体,所以我就这样编码了。
<h3>Grandchild component</h3>
<input type="checkbox" @bind:get="@(IsChecked("Variant 1"))" @bind:set="@((e) => ToggleCheckboxAsync("Variant 1"))" />
@code {
[Parameter] public string SelectedVariant { get; set; } = string.Empty;
[Parameter] public EventCallback<string> SelectedVariantChanged { get; set; }
private bool IsChecked(string value)
=> SelectedVariant == value;
private async Task ToggleCheckboxAsync(string value)
{
if (this.IsChecked(value))
await this.SelectedVariantChanged.InvokeAsync(string.Empty);
else
await this.SelectedVariantChanged.InvokeAsync(value);
// not required
//StateHasChanged();
}
}
然后孩子:
<h3>Child component</h3>
<GrandChild @bind-SelectedVariant:get="_selectedVariant" @bind-SelectedVariant:set="this.OnVariantChanged" />
<h4>Costs: @_costs</h4>
@code {
// this is a calcuated value, not set from the parent
// Parameter, EditorRequired] public int Costs { get; set; } = -1;
[Parameter] public EventCallback<int> CostsChanged { get; set; }
private int _costs;
private string _selectedVariant = string.Empty;
private async Task OnVariantChanged(string value)
{
_selectedVariant = value;
_costs = Random.Shared.Next(5,25);
if (value.Equals("Variant 1"))
_costs = _costs + 100;
await this.CostsChanged.InvokeAsync(_costs);
}
}
还有家:
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
<Child CostsChanged="this.OnCostsChanged" />
<div class="bg-dark text-white m-2 p-2">
<pre>Costs: @_costs</pre>
</div>
@code{
private int _costs;
private Task OnCostsChanged(int value)
{
_costs = value;
return Task.CompletedTask;
}
}