【问题标题】:Blazor Component TwoWay DatabindingBlazor 组件双向数据绑定
【发布时间】: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)

代码进入循环,有人可以解释为什么吗?

【问题讨论】:

    标签: c# blazor 2-way-object-databinding


    【解决方案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 会导致父母知道孩子身上发生的数据变化,应用绑定并更新它的输入。发生的事情是子级使用父级数据进行更新。
    • 在您的评论回复上方查看答案。
    猜你喜欢
    • 2020-03-26
    • 1970-01-01
    • 2022-11-07
    • 2023-02-24
    • 2020-01-15
    • 2021-02-25
    • 2020-10-09
    • 1970-01-01
    • 2021-07-29
    相关资源
    最近更新 更多