我以这种方式制作了Blazor组件:
<input bind-value-oninput="Title" />
@functions {
[Parameter] string Title { get; set; }
[Parameter] EventCallback<string> TitleChanged { get; set; }
}
父母:
@page "/fetchdata"
Parent:<input bind-value-oninput="Title" /> - Child:<Comp bind-Title="Title"></Comp>
@functions {
string Title;
}
如预期的那样,编辑父输入会将其值传播给组件,而不是相反,这是设计使然吗?
通过此编辑,我实现了两种行为:
<input bind-value-oninput="Title" />
@functions {
string _Title { get; set; }
[Parameter] string Title
{
get { return _Title; }
set
{
Console.WriteLine($"{value}->{_Title}");
if (_Title != value)
{
_Title = value;
TitleChanged.InvokeAsync(value);
}
}
}
[Parameter] EventCallback<string> TitleChanged { get; set; }
}
这是实现双向数据绑定的最佳实践吗?然后必须手动调用TitleChanged,对吗?就像WPF的PropertyChanged吗?
无
if (_Title != value)
代码进入循环,有人可以解释为什么?
答案 0 :(得分:0)
这是组件之间的双向数据绑定。此行为(或限制)是设计使然。您所做的是解决该问题的正确方法,我敢说最好的做法,至少根据Steve Anderson的说法,其他人可能会建议其他方法,例如服务类。
发生的事情的一些解释:将更改应用于父组件时,将触发change事件,该组件的状态已更改,并且应重新呈现该组件。要重新渲染父组件,Blazor会自动调用StateHasChanged方法。但是,当子组件的状态发生变化时,父组件对此一无所知,因此我们应该通知它。同样,在我看来,为此使用事件回调是一种很好的做法...
希望这会有所帮助。...
编辑。...
通常,参数流向下,即从父级流到 子,而不是其他方向,因为渲染流程进入 那个方向。这就是为什么无法传递参数的原因 上游(例如布局),因为那时没有单个 定义的渲染顺序。
SteveSanderson
Marco:我不明白的是为什么在父级上调用StateHasChanged会导致数据从父级流向子级,而不是相反。
首先,您无需手动调用StateHasChanged方法。每当触发输入事件时,都会自动调用它。即在按下每个键盘键之后。然后调用它来重新渲染Component(父级)。 (请注意:很容易想到输入标签是HTML输入标签元素,但事实并非如此。)
为什么不是相反:我认为 SteveSanderson 的报价很清楚。
当您要将值(实际上是一个参数,而不是Attribute属性)传递给父组件时,您需要使用其他机制,例如事件(由SteveSanderson推荐);并且在Angular中的工作方式相同)。下面是示例代码如何执行。 重要:当父组件的状态从子组件更改时,我们应该通过手动调用StateHasChanged方法让父组件知道其状态已更改并应重新呈现。使用Action委托时,这是正确的,尽管我认为EventCallback委托应该自动调用StateHasChanged。
组件A.cshtml
// Define a method in the parent component which will be called
// from the child component when the user tap the button residing
// in the child component. This method has a string parameter passed
// from the child component
public void GetValueFromChild(string value)
{
// Do somethig with value
}
组件B.cshtml
// When the user click the button the method GetValueFromChild
// defined on the parent component is called
<button class="btn" onclick=@(() => OnAddValue("some string value"))>Add</button>
@functions
{
// Define an Action delegate property which stores a reference
// to A.GetValueFromChild
// Parameters
[Parameter] Action<string> OnAddValue{ get; set; }
}
A.cshtml
// Here (in the parent component) you place the child component and
// set its OnAddValue to the name of the method to be called
<B OnAddValue = "GetValueFromChild"></B>
如果我的回答对您有帮助,请标记为已接受 希望这会有所帮助...