Blazor组件TwoWay数据绑定

时间:2019-05-14 15:46:57

标签: blazor 2-way-object-databinding

我以这种方式制作了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 个答案:

答案 0 :(得分:0)

这是组件之间的双向数据绑定。此行为(或限制)是设计使然。您所做的是解决该问题的正确方法,我敢说最好的做法,至少根据Steve Anderson的说法,其他人可能会建议其他方法,例如服务类。

发生的事情的一些解释:将更改应用于父组件时,将触发change事件,该组件的状态已更改,并且应重新呈现该组件。要重新渲染父组件,Blazor会自动调用StateHasChanged方法。但是,当子组件的状态发生变化时,父组件对此一无所知,因此我们应该通知它。同样,在我看来,为此使用事件回调是一种很好的做法...

希望这会有所帮助。...

编辑。...

  

通常,参数流向下,即从父级流到   子,而不是其他方向,因为渲染流程进入   那个方向。这就是为什么无法传递参数的原因   上游(例如布局),因为那时没有单个   定义的渲染顺序。

SteveSanderson

Marco:我不明白的是为什么在父级上调用StateHasChanged会导致数据从父级流向子级,而不是相反。

首先,您无需手动调用StateHasChanged方法。每当触发输入事件时,都会自动调用它。即在按下每个键盘键之后。然后调用它来重新渲染Component(父级)。 (请注意:很容易想到输入标签是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> 

如果我的回答对您有帮助,请标记为已接受 希望这会有所帮助...