Blazor 数据绑定开发人员指南
如今,大多数网络应用程序要么在页面上显示某种数据,要么使用表单从用户那里收集数据。这意味着每个 SPA 框架都必须支持数据绑定,以便开发人员可以将数据与标签、表单控件等元素进行绑定。 Blazor 组件内置了对数据绑定的支持,它们同时支持单向和双向数据使用多种技术进行绑定。在本教程中,我将通过一个简单的卡片设计器示例介绍 Blazor 数据绑定功能的基础知识,其中用户将能够实时查看其卡片设计的更新情况。
单向绑定
在单向数据绑定中,数据沿一个方向流动。应用程序代码更新值以响应某些事件或用户操作,当值更新时,相应的 UI 也会动态更新。在单向数据绑定中,不允许用户直接更改值。在 Blazor 中,我们通常使用 @ 符号后跟属性、字段,甚至是一种方法来实现单向数据绑定。例如,如果您的代码中有一个 Title 属性,并且您想将它与 h1 元素绑定,那么您可以编写类似于以下代码段的代码。
<h1>@TItle</h1>
现在要更新代码中的 Title,您可以使用一个简单的按钮 onclick 事件,该事件可以调用代码中的 UpdateTitle 方法来更新 Title 属性的值。只要用户单击按钮,h1 元素文本就会自动更新,因为更新的值会自动从代码流到用户界面。
<button @onclick="UpdateTitle">Update Title</button>
@code{
public string Title { get; set; } = "Hello";
private void UpdateTitle()
{
Title = "Hello, Blazor!";
}
}
双向绑定
在双向数据绑定中,数据在两个方向上流动。通常,用户在前端以某种形式更新值,然后在后端的代码中自动更新该值,然后此更新的值流向 UI 并更新绑定到该值的所有元素。在 Blazor 中,可以使用 @bind 属性实现双向数据绑定,该属性可以以多种方式使用。以下简单示例演示了 @bind 属性的基本用法,其中我们使用 @bind=Property 语法将 Title 属性与输入元素绑定。
<h1>@Title</h1>
<input @bind="Title" />
@code {
public string Title { get; set; } = "Blazor";
}
我们还可以将某个属性绑定到特定事件,以便该属性值仅在该特定事件发生时更新。绑定到特定事件的语法是@bind:event=”EVENT NAME”。例如,在以下代码片段中,如果用户将焦点从输入字段移开,我只想更改 Title 属性。
<h1>@Title</h1>
<input @bind="Title" @bind:event=”onchange” />
@code {
public string Title { get; set; } = "Blazor";
}
现在已经掌握了 Blazor 数据绑定的基本知识,因此,在剩余的教程中,我将向您展示一些使用数据绑定的真实示例。在我们开始之前,请确保您熟悉创建和使用 Blazor 组件。如果您不知道如何创建 Blazor 应用程序或组件,我建议您阅读之前的文章 Blazor 组件初学者指南。
实战应用
在 Visual Studio 2019 中创建一个 Blazor 服务器应用,并在 Pages 文件夹中添加一个新的 Blazor 组件 CardDesigner.razor。我们想要构建一个简单的卡片设计器页面,允许用户同时设计和预览卡片。让我们在新创建的组件的 razor 视图中添加以下 HTML 标记。
CardDesigner.razor
@page "/"
<h1>Card Designer (Blazor Data Binding)</h1>
<div class="container">
<div class="row">
<div class="col-8">
<h3>Design</h3>
<form>
<div class="form-group">
<label for="Heading">Heading</label>
<input type="text" class="form-control" id="Heading">
</div>
<div class="form-group">
<label for="Description">Description</label>
<textarea class="form-control" id="Description" rows="4"></textarea>
</div>
<button class="btn btn-secondary mb-2">Reset</button>
</form>
</div>
<div class="col-4">
<h3>Preview</h3>
<div class="card bg-light w-100">
<div class="card-header">
Heading
</div>
<div class="card-body">
<p class="card-text">
Description
</p>
</div>
</div>
</div>
</div>
</div>
您还需要在 wwwroot/css/site.css 文件中添加一些基本的 CSS 样式,以确保我们的卡片设计器看起来赏心悦目。
site.css
.container {
margin: 15px;
padding: 0px;
}
.col-8, .col-4 {
border: 1px solid #dadada;
padding: 10px;
}
h1 {
font-size: 22px;
font-weight: bold;
margin-bottom: 30px;
margin-top: 20px;
}
h3 {
font-size: 18px;
font-weight: bold;
margin-bottom: 25px;
}
运行该应用程序,您应该能够看到类似于以下内容的页面。左侧是设计部分,允许用户设置卡片的标题和描述,右侧是卡片预览。还有一个重置按钮可以将表单重置为默认值。
让我们为卡片设计器的实现逻辑创建一个单独的代码隐藏部分类。该类有两个简单的属性 Heading 和 Description,并带有一些默认值。当用户单击“重置”按钮时,我们将调用一个方法 ResetCard,该方法会将两个属性重置为其默认值。
CardDesigner.razor.cs
public partial class CardDesigner
{
public string Heading { get; set; } = "Heading";
public string Description { get; set; } = "Description";
public void ResetCard(MouseEventArgs e)
{
Heading = "Heading";
Description = "Description";
}
}
我们现在准备好看到 Blazor 数据绑定功能的实际应用。让我们先从单向数据绑定开始。让我们稍微更新上面的代码,并使用 @ 符号和属性名称添加单向绑定。我将 input 和 textarea 元素的 value 属性与 Heading 和 Description 属性绑定,然后我添加了 @onchange 事件以使用 Lambda 表达式语法更改 Heading 属性。我还附加了 ResetCard 方法和 Reset 按钮的 onclick 事件。
CardDesigner.razor
<form>
<div class="form-group">
<label for="Heading">Heading</label>
<input type="text" class="form-control" id="Heading" value="@Heading"
@onchange="@(e => { Heading = e.Value.ToString(); })">
</div>
<div class="form-group">
<label for="Description">Description</label>
<textarea class="form-control" id="Description" rows="4"
@onchange="@(e => { Description = e.Value.ToString(); })" value="@Description"></textarea>
</div>
<button type="button" class="btn btn-secondary mb-2" @onclick="ResetCard">Reset</button>
</form>
我们还需要使用单向数据绑定更新我们的预览部分卡片,以便每次代码中的标题或描述更新时,预览部分都会自动在卡片上呈现更新的值。
CardDesigner.razor
<div class="card text-white w-100 @SelectedStyleCssClass">
<div class="card-header">
@Heading
</div>
<div class="card-body">
<p class="card-text">
@Description
</p>
</div>
</div>
如果您现在运行您的应用程序,您将看到类似于以下内容的输出。尝试在设计区域输入一些标题和描述,您会注意到,一旦您离开焦点或离开输入字段,预览区域将自动即时更新。
如果您不喜欢在 HTML 中使用 Lambda 表达式,您还可以在代码中定义 UpdateHeading 和 UpdateDescription 方法,然后这些方法可以与 @onchange 事件相关联。
CardDesigner.razor
form>
<div class="form-group">
<label for="Heading">Heading</label>
<input type="text" class="form-control" id="Heading" value="@Heading"
@onchange="UpdateHeading">
</div>
<div class="form-group">
<label for="Description">Description</label>
<textarea class="form-control" id="Description" rows="4"
value="@Description"
@onchange="UpdateDescription"></textarea>
</div>
<button type="button" class="btn btn-secondary mb-2" @onclick="ResetCard">Reset</button>
</form>
CardDesigner.razor.cs
public partial class CardDesigner
{
public string Heading { get; set; } = "Heading";
public string Description { get; set; } = "Description";
public void ResetCard(MouseEventArgs args)
{
Heading = "Heading";
Description = "Description";
}
public void UpdateHeading(ChangeEventArgs e)
{
Heading = e.Value.ToString();
}
public void UpdateDescription(ChangeEventArgs e)
{
Description = e.Value.ToString();
}
}
到目前为止,我们只在我们的应用程序中使用单向绑定,因为 Heading 和 Description 属性的值在我们的代码中更新,我们的代码只有在用户离开表单控件时才会执行。让我们更新示例的代码,看看如何在示例中使用双向数据绑定。使用@bind 属性将 Heading 和 Description 属性与表单控件绑定。我还希望在用户开始在表单控件中输入时立即更新卡片预览。为此,请将 @bind:event="oninput" 添加到 input 和 textarea 控件中。
CardDesigner.razor
<form>
<div class="form-group">
<label for="Heading">Heading</label>
<input type="text" class="form-control" id="Heading" @bind="Heading" @bind:event="oninput">
</div>
<div class="form-group">
<label for="Description">Description</label>
<textarea class="form-control" id="Description" rows="4" @bind="Description" @bind:event="oninput"></textarea>
</div>
<button type="button" class="btn btn-secondary mb-2" @onclick="ResetCard">Reset</button>
</form>
现在双向绑定就位,因此我们不需要手动更新属性,因此我们可以从代码中删除 UpdateHeading 和 UpdateDescription 方法。
CardDesigner.razor.cs
public partial class CardDesigner
{
public string Heading { get; set; } = "Heading";
public string Description { get; set; } = "Description";
public void ResetCard(MouseEventArgs args)
{
Heading = "Heading";
Description = "Description";
}
}
再次运行应用程序并在设计表单中输入标题和描述,然后查看卡片预览如何自动更新。
让我们进一步扩展我们的示例并在设计区域引入一个下拉控件。此下拉列表将显示不同的卡片样式,用户将能够使用双向数据绑定立即选择和应用任何卡片样式。让我们在 Data 文件夹中添加以下 StyleInfo 类。
StyleInfo.cs
public class StyleInfo
{
public string Name { get; set; }
public string CssClass { get; set; }
}
让我们在 CardDesigner.razor.cs 文件中再添加两个属性来存储可用卡片样式的列表并存储所选样式的引用。我们在名为 OnInitialized 的组件初始化方法之一中初始化 Styles 属性。 OnInitialized 方法在从父组件接收到初始参数后初始化组件时调用。
CardDesigner.razor.cs
public partial class CardDesigner
{
public string Heading { get; set; } = "Heading";
public string Description { get; set; } = "Description";
public List<StyleInfo> Styles { get; set; }
public string SelectedStyleCssClass { get; set; }
protected override void OnInitialized()
{
Styles = new List<StyleInfo>()
{
new StyleInfo() { Name = "Primary", CssClass = "bg-primary" },
new StyleInfo() { Name = "Secondary", CssClass = "bg-secondary" },
new StyleInfo() { Name = "Success", CssClass = "bg-success" }
};
SelectedStyleCssClass = "bg-primary";
}
public void ResetCard(MouseEventArgs args)
{
Heading = "Heading";
Description = "Description";
}
}
最后,我们需要在 CardDesigner.razor 文件中添加一个 HTML select 元素。我们正在运行一个简单的 @foreach 循环来迭代 Styles 属性并在循环内创建元素。元素的 value 属性将呈现 CssClass 属性值,每个元素的文本将使用 Name 属性呈现。
CardDesigner.razor
<div class="form-group">
<label for="Style">Style</label>
<select class="form-control" id="Style" @bind="SelectedStyleCssClass" @bind:event="onchange">
@foreach (var style in Styles)
{
<option value="@style.CssClass">@style.Name</option>
}
</select>
</div>
在上面的代码片段中,我们使用@bind 属性将 SelectedStyleCssClass 属性与 select 元素绑定,并且我们决定使用 onchange 事件和 select 以便每次用户从下拉列表中选择一个选项时,卡片样式都会自动更新。
如果您现在运行该项目,您将看到下拉列表中填充的样式,并且所选样式也应用于预览部分中的卡片。
右键单击 select 元素并选择 Inspect 菜单选项以查看选项在 HTML 中的呈现方式以及每个选项的值如何包含我们在代码中初始化的 CssClass 属性。
尝试从下拉列表中选择不同的样式,卡片预览将立即更新。
总结概括
在本教程中,介绍了 Blazor 数据绑定的基础知识。我们已经学习了如何使用单向和双数据绑定功能以及如何使用数据绑定更新值。我们还学习了如何使用不同的事件来指定应该更新值的时间。
您的资助是我最大的动力!
金额随意,欢迎来赏!