c# - Blazor 组件双向数据绑定
问题描述
我以这种方式制作了 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)
代码进入循环,有人可以解释为什么?
解决方案
This is a two-way data binding between components. This behavior (or limitation) is by design. What you do, is the correct way to solve it, and I may venture to say, a best practice, at least according Steve Anderson, others may suggest different methods, such as a service class.
Some explanation of what is going on: When you apply a change to the parent component, the change event is triggered, the state of the component has changed, and the component should be re-rendered. To re-render the parent component, the StateHasChanged method is called by Blazor automatically. But when a state is changed on the child component, the parent component is ignorant of this, and we should notify it of this. Again, using event call backs for this is a good practice, to my mind...
Hope this helps....
Edit....
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.
SteveSanderson
Marco: What I don't understand is why calling StateHasChanged on the parent causes the data to flow from the parent to the child and not the opposite.
First off, you don't manually call the StateHasChanged method. It is automatically called whenever the input event is triggered; that is after each keyboard key is pressed. And it is called to rerender the Component(parent). ( Note: It is tempting to think that the input tag is an HTML input tag element, but it is not so.)
As for why not the opposite: I think the quotation by SteveSanderson made it very clear.
When you want to pass a value (This is actually a parameter, but not an Attribute property) to the Parent Component, you need to use a different mechanism such as events (recommended by SteveSanderson; and work the same like in Angular). Below is sample code how it is performed. Important: When the state of the Parent Component is being changed from a child component, we should let the Parent Component to know that its state has changed and that it should rerender, by manually calling the StateHasChanged method. This is true when using the Action delegate, though I think that the EventCallback delegate is supposed to call StateHasChanged automatically.
Component 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
}
Component 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>
Please mark my answer as accepted if it helped you out Hope this helps...
推荐阅读
- javascript - webpack:字符串中的逗号导致捆绑期间的语法错误
- python - python web应用程序,无需单独服务器即可触发异步功能
- javascript - 本地存储的 JWT 安全性
- javascript - 如何从 JavaScript 执行 Kotlin WebAssembly 函数?
- python - 为 LSTM 整形数据,并将密集层的输出馈送到 LSTM
- python - 通过 Celery 连接两个独立的项目
- javascript - 通过 websockets 提交和刷新后表单(react 组件)不可用
- react-native - React Native Modal 中的绝对位置在不同设备上不一致
- javascript - 如何使用 Javascript 从 API 获得部分大响应?
- intellij-idea - IntelliJ 显示误报错误