【问题标题】:Is there an easy way to signal changes to data happening in child component?有没有一种简单的方法来表示子组件中发生的数据更改?
【发布时间】:2020-06-09 00:49:17
【问题描述】:

假设我的页面中有一组通过 OnInitializedAsync() 加载的数据。数据以图形方式显示在表格中,但稍后还会在页面下方的另一个表格中更详细地显示。 由于明细表中的行有很多控件和逻辑,我决定为该行制作一个组件,例如<RowData Data="@rowdata" />并绑定每一行数据。

问题是,如果我的子控制器 (RowData) 中的数据发生更改,它不会反映在我的“父”组件中的第一个表中,其中也列出了相同的数据。

是否有一种简单的方法来表示更改或者我应该避免制作子组件?

我通过在我的子组件中创建一个 EventCallback 并通过我的父组件中的回调进行更新来解决它。但我有一种感觉,我错过了一些东西。

【问题讨论】:

标签: c# blazor


【解决方案1】:

以下示例展示了如何在父节点之间执行双向数据绑定 组件及其子组件。在这两个组件中的每一个都是一个文本框控件。当您在父组件的文本框中键入文本时,子组件文本框中的文本会更改以反映在父组件中所做的更改, 反之亦然……

ChildComponent.razor

    <div style="border:solid 1px red">
        <h2>Child Component</h2>
         <input type="text" @bind="Text" @bind:event="oninput" />
    </div>

@code {
    private string text { get; set; }

    [Parameter]
    public string Text
    {
        get { return text; }
        set
        {
            if (text != value) {
                text = value;
                if (TextChanged.HasDelegate)
                {
                    TextChanged.InvokeAsync(value);
                }
            }
        }
    }

    [Parameter]
    public EventCallback<string> TextChanged { get; set; }
}

ParentComponent.razor

@page "/ParentComponent"

<h1>Parent Component</h1>

<input type="text" @bind="Text" @bind:event="oninput" />
<p></p>

<ChildComponent @bind-Text="Text" />


@code {
    [Parameter]
    public string Text { get; set; } = "Hello Blazor";
}

我通过在我的子组件中创建一个 EventHandler 并通过回调进行更新来解决它。但我觉得我错过了一些东西

您缺少的是本示例中用于调用父组件并将在子组件中输入的值传递给它的 EventCallback 'delegate' 的存在。这就是我们定义“委托”的方式

 [Parameter]
 public EventCallback<string> TextChanged { get; set; }

这就是我们调用它的方式,当 Text 属性的值发生变化时:

TextChanged.InvokeAsync(value);

你使用了什么委托?注意EventCallback的目标不是子组件,而是父组件……

祝你好运...如果有不清楚的地方,请不要犹豫...

【讨论】:

  • 我确实有一个 EventCallback,正如我所说,我确实解决了它,但可能正在寻找一个更简单的解决方案,但我想这就是你的做法。不过,我会将您的答案标记为解决方案。
  • 我猜我希望通过某种级联更新魔法实现更简单的 2 向绑定。不过,Blazor 本身就有很多魔力 :)
  • 这种方法在涉及父子组件的时候最合适。但是,如果您必须在涉及更多组件、相互嵌套等时维护状态,您可以创建一个状态服务。还有专门用于状态管理的库。
【解决方案2】:

如果您有一个具有 N 级嵌套组件的根组件(子组件中的子组件),那么您可以使用级联值。试试这样的

public class MyState
{
  public List<MyObject> Objects { get; set; }
  public Action OnModified { get; }

  public MyState(List<MyObject> objects, Action onModified)
  {
    Objects = objects;
    OnModified = onModified;
  }
}

在你的父组件中

MyState State;

protected override OnInitialized()
{
  State = new MyState(your objects, () => InvokeAsync(StateHasChanged));
}

在你的父标记中

<CascadingValue Value=State>
  All your child content here
</CascadingValue>

在您需要访问的各种子组件中

[CascadingParameter]
public MyState State { get; set; }

protected void SomeEditWasMade()
{
  State.Objects[23].Name = "Bob";
  State.OnModified();
}

这应该调用父级中的() =&gt; InvokeAsync(StateHasChanged),然后该组件和使用MyState 级联值的每个组件都将被重新渲染。

或者你可以使用类似Fluxor :)

【讨论】:

    猜你喜欢
    • 2011-10-26
    • 1970-01-01
    • 2020-10-18
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多