ASP.NET Core Blazor 数据绑定ASP.NET Core Blazor data binding
本文内容
作者:Luke Latham 和 Daniel Roth
Razor 组件通过名为 @bind
的 HTML 元素特性提供了数据绑定功能,该特性具有字段、属性或 Razor 表达式值。
下面的示例将 CurrentValue
属性绑定到文本框的值:
<input @bind="CurrentValue" />
@code {
private string CurrentValue { get; set; }
}
当文本框失去焦点时,该属性的值会更新。
仅当呈现组件时(而不是响应属性值更改),才会在 UI 中更新文本框。由于组件会在事件处理程序代码执行之后呈现自己,因此在触发事件处理程序之后,通常会 在 UI 中反映属性更新。
将 @bind
与 CurrentValue
属性结合使用 (<input @bind="CurrentValue" />
) 在本质上等效于以下内容:
<input value="@CurrentValue"
@onchange="@((ChangeEventArgs __e) => CurrentValue =
__e.Value.ToString())" />
@code {
private string CurrentValue { get; set; }
}
呈现组件时,输入元素的 value
来自 CurrentValue
属性。用户在文本框中键入并更改元素焦点时,会激发 onchange
事件并将 CurrentValue
属性设置为更改的值。实际上,代码生成更加复杂,因为 @bind
会处理执行类型转换的情况。原则上,@bind
将表达式的当前值与 value
属性关联,并使用注册的处理程序处理更改。
通过同时包含带有 event
参数的 @bind:event
属性,在其他事件上绑定属性或字段。以下示例在 oninput
事件上绑定 CurrentValue
属性:
<input @bind="CurrentValue" @bind:event="oninput" />
@code {
private string CurrentValue { get; set; }
}
与在元素失去焦点时激发的 onchange
不同,oninput
在文本框的值更改时激发。
通过 @bind-{ATTRIBUTE}:event
语法使用 @bind-{ATTRIBUTE}
可绑定除 value
之外的元素属性。在下面的示例中,当 _paragraphStyle
值更改时,段落的样式会更新:
@page "/binding-example"
<p>
<input type="text" @bind="_paragraphStyle" />
</p>
<p @bind-style="_paragraphStyle" @bind-style:event="onchange">
Blazorify the app!
</p>
@code {
private string _paragraphStyle = "color:red";
}
属性绑定是区分大小写的。例如,@bind
有效,而 @Bind
无效。
无法分析的值Unparsable values
如果用户向数据绑定元素提供无法分析的值,则在触发绑定事件时,无法分析的值会自动还原为以前的值。
请参考以下方案:
<input>
元素绑定到int
类型,其初始值为123
:
<input @bind="MyProperty" />
@code {
[Parameter]
public int MyProperty { get; set; } = 123;
}
- 用户在页面中将该元素的值更新为
123.45
,并更改元素焦点。
在上面的方案中,元素的值会还原为 123
。如果拒绝值 123.45
以采用原始值 123
,则用户会了解其值不被接受。
默认情况下,绑定适用于元素的 onchange
事件 (@bind="{PROPERTY OR FIELD}"
)。使用 @bind="{PROPERTY OR FIELD}" @bind:event={EVENT}
对其他事件触发绑定。对于 oninput
事件 (@bind:event="oninput"
),在任何引入无法分析的值的击键之后,会进行还原。当使用 int
绑定类型以 oninput
事件为目标时,会阻止用户键入 .
字符。.
字符会立即删除,因此用户会收到仅允许整数的即时反馈。在某些情况下,在 oninput
事件中还原值并不理想,例如在应该允许用户清除无法解析的 <input>
值时。替代方案包括:
- 不使用
oninput
事件。使用默认onchange
事件(仅指定@bind="{PROPERTY OR FIELD}"
),其中无效值在元素失去焦点之前不会还原。 - 绑定到可以为 null 的类型(如
int?
或string
),并提供自定义逻辑来处理无效条目。 - 使用窗体验证组件,如
InputNumber
或InputDate
。窗体验证组件具有用于管理无效输入的内置支持。窗体验证组件:- 允许用户提供无效输入并在关联的
EditContext
上接收验证错误。 - 在 UI 中显示验证错误,而不干扰用户输入其他 webform 数据。
- 允许用户提供无效输入并在关联的
格式字符串Format strings
数据绑定使用 @bind:format
处理 DateTime 格式字符串。目前无法使用其他格式表达式,如货币或数字格式。
<input @bind="StartDate" @bind:format="yyyy-MM-dd" />
@code {
[Parameter]
public DateTime StartDate { get; set; } = new DateTime(2020, 1, 1);
}
在前面的代码中,<input>
元素的字段类型 (type
) 默认为 text
。对于绑定以下 .NET 类型,支持 @bind:format
:
@bind:format
属性指定要应用于 <input>
元素的 value
的日期格式。该格式还用于在 onchange
事件发生时分析值。
不建议为 date
字段类型指定格式,因为 Blazor 具有用于设置日期格式的内置支持。尽管提出了建议,但如果使用 date
字段类型提供格式,则只有使用 yyyy-MM-dd
日期格式才能使绑定正常工作:
<input type="date" @bind="StartDate" @bind:format="yyyy-MM-dd">
使用组件参数的父级到子级绑定Parent-to-child binding with component parameters
绑定可识别组件参数,其中 @bind-{PROPERTY}
可以将属性值从父组件向下绑定到子组件。在使用链接绑定的子级到父级绑定部分中,介绍了从子级绑定到父级。
以下子组件 (ChildComponent
) 具有 Year
组件参数和 YearChanged
回调:
<h2>Child Component</h2>
<p>Year: @Year</p>
@code {
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
}
EventCallback<T>
在 ASP.NET Core Blazor 事件处理 中进行了说明。
以下父组件使用:
ChildComponent
并将ParentYear
参数从父级绑定到子组件上的Year
参数。onclick
事件用于触发ChangeTheYear
方法。有关详细信息,请参阅 ASP.NET Core Blazor 事件处理。
@page "/ParentComponent"
<h1>Parent Component</h1>
<p>ParentYear: @ParentYear</p>
<ChildComponent @bind-Year="ParentYear" />
<button class="btn btn-primary" @onclick="ChangeTheYear">
Change Year to 1986
</button>
@code {
[Parameter]
public int ParentYear { get; set; } = 1978;
private void ChangeTheYear()
{
ParentYear = 1986;
}
}
加载 ParentComponent
会生成以下标记:
<h1>Parent Component</h1>
<p>ParentYear: 1978</p>
<h2>Child Component</h2>
<p>Year: 1978</p>
如果通过在 ParentComponent
中选择按钮来更改 ParentYear
属性的值,则会更新 ChildComponent
的 Year
属性。当重新呈现 ParentComponent
时,Year
的新值会呈现在 UI 中:
<h1>Parent Component</h1>
<p>ParentYear: 1986</p>
<h2>Child Component</h2>
<p>Year: 1986</p>
Year
参数是可绑定的,因为它具有与 Year
参数类型相匹配的伴随 YearChanged
事件。
按照约定,<ChildComponent @bind-Year="ParentYear" />
在本质上等效于编写:
<ChildComponent @bind-Year="ParentYear" @bind-Year:event="YearChanged" />
通常,可以通过包含 @bind-{PROPRETY}:event
特性将属性绑定到对应的事件处理程序。例如,可以使用以下两个特性将属性 MyProp
绑定到 MyEventHandler
:
<MyComponent @bind-MyProp="MyValue" @bind-MyProp:event="MyEventHandler" />
使用链接绑定的子级到父级绑定Child-to-parent binding with chained bind
一种常见方案是将数据绑定参数链接到组件输出中的页面元素。此方案称为链接绑定 ,因为多个级别的绑定会同时进行。
无法在页面元素中使用 @bind
语法实现链接绑定。必须单独指定事件处理程序和值。但是,父组件可以将 @bind
语法用于组件的参数。
以下 PasswordField
组件 (PasswordField.razor ):
- 将
<input>
元素的值设置为Password
属性。 - 使用 EventCallback 向父组件公开
Password
属性的更改。 - 使用
onclick
事件触发ToggleShowPassword
方法。有关详细信息,请参阅 ASP.NET Core Blazor 事件处理。
<h1>Child Component</h2>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(_showPassword ? "text" : "password")"
value="@Password" />
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
@code {
private bool _showPassword;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
Password = e.Value.ToString();
return PasswordChanged.InvokeAsync(Password);
}
private void ToggleShowPassword()
{
_showPassword = !_showPassword;
}
}
PasswordField
组件在另一个组件中使用:
@page "/ParentComponent"
<h1>Parent Component</h1>
<PasswordField @bind-Password="_password" />
@code {
private string _password;
}
对前面示例中的密码执行检查或捕获错误:
- 为
Password
创建支持字段(在下面的示例代码中为_password
)。 - 在
Password
资源库中执行检查或捕获错误。
如果密码的值中使用了空格,则以下示例会向用户提供即时反馈:
@page "/ParentComponent"
<h1>Parent Component</h1>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(_showPassword ? "text" : "password")"
value="@Password" />
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
<span class="text-danger">@_validationMessage</span>
@code {
private bool _showPassword;
private string _password;
private string _validationMessage;
[Parameter]
public string Password
{
get { return _password ?? string.Empty; }
set
{
if (_password != value)
{
if (value.Contains(' '))
{
_validationMessage = "Spaces not allowed!";
}
else
{
_password = value;
_validationMessage = string.Empty;
}
}
}
}
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
Password = e.Value.ToString();
return PasswordChanged.InvokeAsync(Password);
}
private void ToggleShowPassword()
{
_showPassword = !_showPassword;
}
}
单选按钮Radio buttons
有关绑定到窗体中的单选按钮的信息,请参阅 ASP.NET Core Blazor 窗体和验证。