如何让两种方式的数据绑定在 blazor 中工作?

Posted

技术标签:

【中文标题】如何让两种方式的数据绑定在 blazor 中工作?【英文标题】:How to get two way databindings working in blazor? 【发布时间】:2021-02-01 17:37:38 【问题描述】:

我有以下类似于TextBox 组件的组件。但是由于某种原因,Value 的内容似乎从未改变。

我希望这可以在没有手动 javascript 的情况下与数据绑定一起使用,不是吗?


<div class="form-group">
    <input type="text" class="form-control" @bind="Value" @onkeyup="OnKeyUp" placeholder="@Placeholder"/>
</div>

@code 
    
    [Parameter]
    public string Value  get; set; 

    [Parameter]
    public EventCallback<string> ValueChanged  get; set; 

    [Parameter]
    public string Placeholder  get; set; 

    private void OnKeyUp(KeyboardEventArgs obj)
    
        ValueChanged.InvokeAsync(Value);
    


【问题讨论】:

【参考方案1】:

您不应绑定到 [Parameter],因为它可能会导致副作用 (see Steve Sanderson's comment here)

您似乎希望对每个更改进行两种绑定,为此我会使用oninput 而不是onkeyup,但如果您确实需要,您可以使用onkeyup

主要是绑定到本地,永远不要手动更改公共参数:

<div class="form-group">
    <input type="text" class="form-control" 
           @bind-value=@InternalValue 
           @bind-value:event="oninput" 
           placeholder="@Placeholder"/>
</div>

@code 

    string InternalValue
    
        get => Value;
        set 
        
            if (value!=Value)
            
                ValueChanged.InvokeAsync(value);        
            
        
    

    [Parameter]
    public string Value  get; set; 

    [Parameter]
    public EventCallback<string> ValueChanged  get; set; 

    [Parameter]
    public string Placeholder  get; set; 

编辑:添加史蒂夫·桑德森的笔记以防它们消失...

Steve Sanderson 引用上面链接的 GitHub 问题:

好的,我已经更详细地查看了,看看发生了什么。有一个 下面的解释,但在此之前,我将重申我的主张 核心问题是子组件覆盖了自己的 [参数] 属性值。通过避免这样做,您可以避免这种情况 问题。

在这种情况下以及在其他情况下,Blazor 依赖于父对子 参数分配是安全的(不覆盖你想要的信息 保持)并且没有副作用,例如触发更多渲染 (因为那样你可能会陷入无限循环)。我们大概应该 加强文档中的指导,而不仅仅是说“不要写信给你的 自己的参数”并扩展它以警告不要产生副作用 在这样的属性设置器中。 Blazor 使用 C# 属性来表示 从父组件到子组件的通信通道很漂亮 方便开发人员并且在源代码中看起来不错,但是 副作用的能力是有问题的。我们已经有一个 编译时分析器,如果你没有正确的警告 [Parameter] 属性上的可访问性修饰符 - 也许我们应该 如果参数是其他参数,则扩展它以给出警告/错误 比简单的 get;放; 自动属性。

所以在这种情况下,解决方案非常简单:替换 Component1 的 具有简单 get; 的值属性放;一个,而不是 试图写入它,让 Component1 响应按钮点击 触发 ValueChanged。然后你没有任何递归渲染 循环,不会发生数据覆盖。

private void DecrementValue()

    //Value--; <-- Don't do this

    // Do this instead:
    ValueChanged.InvokeAsync(Value - 1);

【讨论】:

以上是关于如何让两种方式的数据绑定在 blazor 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 System.Diagnostics 在 Ubuntu Linux 上的 Blazor 应用程序中工作?

如何在 Blazor 中以两种方式绑定级联值?

[Inject] 有问题,不能在 C# 类 (Blazor) 中工作

会话如何在 Laravel 5 中工作

如何让这个 Javascript 字谜算法在 Ruby 中工作?

Silverlight 数据绑定无法从可编写脚本的成员中工作