Blazor 组件双向数据绑定
Posted
技术标签:
【中文标题】Blazor 组件双向数据绑定【英文标题】:Blazor Component TwoWay Databinding 【发布时间】:2019-10-01 16:56:41 【问题描述】:我以这种方式制作了 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)
代码进入循环,有人可以解释为什么吗?
【问题讨论】:
【参考方案1】:这是组件之间的双向数据绑定。这种行为(或限制)是设计使然。你所做的是解决它的正确方法,我可以冒昧地说,一个最佳实践,至少根据史蒂夫安德森,其他人可能会建议不同的方法,例如服务类。
对发生的事情的一些解释:当您对父组件应用更改时,会触发更改事件,组件的状态发生了变化,并且应该重新渲染组件。若要重新呈现父组件,Blazor 会自动调用 StateHasChanged 方法。但是当子组件的状态发生变化时,父组件对此一无所知,我们应该通知它。同样,在我看来,为此使用事件回调是一个好习惯......
希望这有帮助....
编辑....
一般来说,参数流是向下的,即从父级到 孩子,而不是另一个方向,因为渲染流进入 那个方向。这就是为什么没有办法传递参数的原因 上游(例如,布局),因为那时没有单一的 定义的渲染顺序。
史蒂夫桑德森
Marco:我不明白为什么对父级调用 StateHasChanged 会导致数据从父级流向子级,而不是相反。
首先,您无需手动调用 StateHasChanged 方法。每当触发输入事件时都会自动调用它;即在按下每个键盘键之后。并调用它来重新渲染组件(父)。 (注意:很容易认为输入标签是一个 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>
如果对您有帮助,请将我的回答标记为已接受 希望这会有所帮助...
【讨论】:
感谢您的回答,我做了更多的测试,但我不明白为什么在父级上调用 StateHasChanged 会导致数据从父级流向子级而不是相反.我在孩子身上设置了输入,现在正如你所说,父母不知道,我希望在父母上调用 StateHasChanged 会导致父母知道孩子身上发生的数据变化,应用绑定并更新它的输入。发生的事情是子级使用父级数据进行更新。 在您的评论回复上方查看答案。以上是关于Blazor 组件双向数据绑定的主要内容,如果未能解决你的问题,请参考以下文章