我用这种方式制作了 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; }
}
这是实现双向数据绑定(bind)的最佳实践吗?那么TitleChanged必须手动调用,对吧?是不是像WPF的PropertyChanged?
没有
if (_Title != value)
代码进入循环,有人可以解释为什么吗?
最佳答案
这是组件之间的双向数据绑定(bind)。此行为(或限制)是设计使然。你所做的,是解决问题的正确方法,我可以大胆地说,这是一种最佳实践,至少根据史蒂夫·安德森,其他人可能会建议不同的方法,例如服务类。
对发生的情况的一些解释:当您对父组件应用更改时,会触发更改事件,组件的状态已更改,并且应重新渲染组件。为了重新渲染父组件,Blazor 会自动调用 StateHasChanged 方法。但是,当子组件上的状态发生更改时,父组件对此一无所知,我们应该通知它。再次强调,在我看来,使用事件回调是一个很好的做法......
希望这有帮助......
编辑...
In general the parameter flow goes downwards, i.e., from parent to child, not in the other direction, because the rendering flow goes in that direction. That's why there isn't a way to pass parameters upstream (e.g., to a layout), because then there's be no single defined render order.
史蒂夫桑德森
Marco:我不明白的是为什么在父级上调用 StateHasChanged 会导致数据从父级流向子级,而不是相反。
首先,您不需要手动调用 StateHasChanged 方法。每当输入事件被触发时就会自动调用;即按下每个键盘按键后。并调用它来重新渲染组件(父组件)。 (注意:人们很容易认为 input 标签是 HTML 输入标签元素,但事实并非如此。)
至于为什么不相反:我认为SteveSanderson的引言已经说得很清楚了。
当你想向父组件传递一个值(这实际上是一个参数,而不是一个 Attribute 属性)时,你需要使用不同的机制,例如事件(SteveSanderson 推荐的;并且与 Angular 中的工作方式相同) )。以下是其执行方式的示例代码。 重要提示:当子组件更改父组件的状态时,我们应该通过手动调用 StateHasChanged 方法让父组件知道其状态已更改并且应该重新渲染。使用 Action 委托(delegate)时确实如此,但我认为 EventCallback 委托(delegate)应该自动调用 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>
如果我的回答对您有帮助,请将其标记为已接受 希望这有帮助...
关于c# - Blazor 组件双向数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56134234/