Value 和@bind-Value 之间的区别?

问题描述 投票:0回答:2

我正在查看

InputCheckBox
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.forms.inputcheckbox 的文档,我发现它公开了
Value 
绑定到所需的布尔值 (
Gets or sets the value of the input. This should be used with two-way binding.
)。尽管如此,世界各地的人们都在使用
@bind-Value
来代替,而且,我无法让
Value
工作。

这怎么样:

<InputCheckbox @bind-Value="model.IsSelected"></InputCheckbox>

与此不同(以及为什么这个不起作用):

<InputCheckbox Value="@model.IsSelected"></InputCheckbox>

我还注意到

@bind-Value
更新/通知模型有关更改并更新依赖于
IsSelected
的任何属性,而
Value
则不会(可能除非明确指定?)。 此外,当使用
Value
时,我还需要为标签添加
ValueExpression
(否则它不会渲染)。这是啥
ValueExpression
??在什么情况下有人会实施不同的
ValueExpression

使用

Value
有什么好处吗?需要什么才能让它发挥作用?我在这里错过了什么吗?

checkbox data-binding binding blazor 2-way-object-databinding
2个回答
5
投票

更多背景信息和解释

InputBase

所有

InputBase
继承的组件都实现三个
Parameters

  1. Value
    是控件的“in”值 - 它是强类型的。
  2. ValueChanged
    是控件的“out”值:具有强类型值的回调。
  3. ValueExpression
    是定义实际模型对象/属性的
    Func
    委托。它在内部用于创建一个
    FieldIdentifier
    对象,该对象用于标识
    EditContext
    ValidationStore
    中的属性。

此页面演示了两种设置绑定的方法。

第一个手动执行此操作并将更改连接到回调方法。当您除了设置值之外还想运行其他代码时,可以使用此选项。 (我正在设置时间戳)。

第二种使用

Razor
提供的“合成糖”。
@bind-Value
告诉 Razor 编译器构建一组代码,将通用名称为
Value
的三个参数链接到提供的模型属性。

@page "/"

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

<InputCheckbox class="form-check"
               @bind-Value=this.model.Value />

<InputCheckbox class="form-check"
               Value=this.model.Value
               ValueChanged=this.OnValueChanged
               ValueExpression="() => this.model.Value" />

<div class="alert alert-info">
    Value: @this.model.Value
</div>

<div class="alert alert-info">
    @this.message
</div>

@code {
    private Model model = new();
    private string message = "No Message";

    private Task OnValueChanged(bool value)
    {
        this.model.Value = value;
        // You can do other stuff here if you need to
        this.message = $"Set at {DateTime.Now.ToLongTimeString()}";
        return Task.CompletedTask;
    }

    public class Model
    {
        public bool Value { get; set; }
    }
}

在编译后的低级 C# 代码中,它们实际上是相同的东西。

这是完整的绑定:

private RenderFragment FirstComponent => __builder =>
{
    __builder.OpenComponent<InputCheckbox>(5);
    __builder.AddAttribute(6, "class", "form-check");
    __builder.AddAttribute(7, "Value", RuntimeHelpers.TypeCheck<Boolean>(this.model.Value));
    __builder.AddAttribute(8, "ValueChanged", RuntimeHelpers.TypeCheck<EventCallback<Boolean>>(EventCallback.Factory.Create<Boolean>(this, RuntimeHelpers.CreateInferredEventCallback(this, __value => this.model.Value = __value, this.model.Value))));
    __builder.AddAttribute(9, "ValueExpression", RuntimeHelpers.TypeCheck<global::System.Linq.Expressions.Expression<System.Func<System.Boolean>>>(() => this.model.Value));
    __builder.CloseComponent();
};

这是手动绑定:

private RenderFragment SecondComponent => __builder =>
{
    __builder.OpenComponent<InputCheckbox>(11);
    __builder.AddAttribute(12, "class", "form-check");
    __builder.AddAttribute(13, "Value", RuntimeHelpers.TypeCheck<global::System.Boolean>(this.model.Value));
    __builder.AddAttribute(14, "ValueChanged", RuntimeHelpers.TypeCheck<EventCallback<Boolean>>(EventCallback.Factory.Create<Boolean>(this, this.OnValueChanged)));
    __builder.AddAttribute(15, "ValueExpression", RuntimeHelpers.TypeCheck<Expression<System.Func<System.Boolean>>>(() => this.model.Value));
    __builder.CloseComponent();
};

Net7.0 @input-value:get 和 @input-value:set

Net7.0 实现了更多的语法糖,让您以另一种方式进行绑定。它还添加了第三个

@input-value:after
绑定,以提供一种方法来执行上面显示的时间戳。

请参阅此处以获取最新的绑定信息 - https://learn.microsoft.com/en-us/aspnet/core/blazor/components/data-binding


3
投票

正如您所注意到的,

@bind-Value
为 Value 提供 2 路绑定。

我做了一次以下演示:

  • 从模板之一启动一个新项目

  • 稍微更改计数器页面:

<p role="status">Current count: @Count</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    [Parameter]
    public int Count { get; set; } = 1;

    [Parameter]
    public EventCallback<int> CountChanged { get; set; }

    public Task IncrementCount()
    {
        return CountChanged.InvokeAsync(Count + 1);        
    }
}
  • 然后在索引页面上:
@page "/"
<div>
    <p>Counter1 : @count1</p>
    <p>Counter2 : @count2</p>
</div>

<Counter @bind-Count="count1"  />

<Counter Count="count2" CountChanged="UpdateCount2" />

@code {
    int count1 = 1;
    int count2 = 2;

    void UpdateCount2(int newValue)
    {
        count2 = newValue;
    }
}

当您现在单击索引页面上的按钮时,两个 Counter 实例的行为完全相同

这是因为对于

@bind-Count
,Razor 编译器会在幕后生成
UpdateCount1
部分(等效)。仅当存在具有正确名称的回调参数时才有效:
CountChanged

请参阅 Blazor 数据绑定

© www.soinside.com 2019 - 2024. All rights reserved.