Blazor带我重玩前端(六)
本文主要讨论Blazor事件内容,由于blazor事件部分很多,所以会分成上下两篇,本文为第二篇。
双向绑定
概述
如图所示
- 当点击单项绑定的时候,MyOnewayComponent里的属性值会发生变化,这种变化是单项的,仅仅只是本地副本的值的变化,并不会引发父页面的值发生变化。但当点击父页面的Click Me的时候,会修改MyOnewayComponent的属性值会被修改。所以单项绑定强调的是占位,以达到动态输出的目的。
- 当点击双向绑定的时候,三个值会同步发生变化。即便点击父页面的Click Me,也不会覆盖掉MyTwoWayComponent的属性值,这说明父页面和MyTwoWayComponent页面的值发生了双向绑定,会导致数据同步变化。
- 双向绑定,绑定的是Blazor组件和dom元素,就像是宏指令一样。也就是说,当该组件首次运行时,输入框的值来自于CurrentValue属性,当用户输入新的值后,CurrentValue也将会被设置成新的值。
示例
双向绑定有一个重要特征就是使用@bind-进行数据绑定,之前我创建了两个组件,我们来看一下这两个组件的源代码:MyOnewayComponent:
<div>
MyComponent CounterValue is @CounterValue
</div>
<button @onclick=UpdateCounterValue>Update</button>
@code {
[Parameter]
public int CounterValue { get; set; }
void UpdateCounterValue()
{
CounterValue++;
}
}
MyTwoWayComponent:
<div>
MyComponent CounterValue is @CounterValue
</div>
<button @onclick=UpdateCounterValue>Update</button>
@code {
[Parameter]
public int CounterValue { get; set; }
[Parameter]
public EventCallback<int> CounterValueChanged { get; set; }
async Task UpdateCounterValue()
{
CounterValue++;
await CounterValueChanged.InvokeAsync(CounterValue);
}
}
以上代码可以看到有明显的不同,MyTwoWayComponent包含一个EventCallback类型的属性,其命名是CounterValueChanged,看起来像是属性值后缀Changed,其调用方法也变成了async Task,该方法表明,当CounterValue发生变化的时候,会通过CounterValueChanged来通知事件源页面该值发生了变化。额外尝试一下,如果我们直接使用MyOnewayComponent 来演示双向绑定,会发生什么,我们使用如下代码运行一下看看:
<MyOnewayComponent @bind-CounterValue="@currentCount" />
运行后,发现报错了,错误信息是:Unhandled exception rendering component: Object of type 'BlazorApp.Client.Pages.MyOnewayComponent' does not have a property matching the name 'CounterValueChanged'。由此可见,我们的命名规则是强制的,其必须是所绑定EventCallBack的属性名后缀Changed。
BuildTree源码
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.AddContent(8, "Click me");
__builder.CloseElement();
__builder.AddMarkupContent(9, "rn<br>rn<br>rnrn");
__builder.OpenComponent<BlazorApp.Client.Pages.MyOnewayComponent>(10);
__builder.AddAttribute(11, "CounterValue", Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<System.Int32>(
#nullable restore
currentCount
#line default
#line hidden
#nullable disable
));
__builder.AddAttribute(12, "CounterValueChanged", Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => currentCount = __value, currentCount));
__builder.CloseComponent();
}
- 8-15行是单项绑定的内容
- 16-18行是双向绑定的内容
级联值和参数
概述
级联值和参数是一种将值从组件传递到其所有子组件的方法,在Blazor中,采用CascadingValue来实现,子组件通过声明同一类型的属性(用[CascadingParameter]属性修饰)来收集并赋值。当级联值发生更新的时候,这种更新将传递到所有的子组件,同时这组件将会自动调用StateHasChanged 。一般情况下,我们的CascadingValue中可能会需要传递多个值的变化,那么这种变化是如何进行的呢。是通过两种方式,一种是类型推导,一种是命名传值。
类型推导
我创建了两个组件,分别是FirstComponent,SecondComponent。FirstComponent源码如下:
<CascadingValue Value="@CascadingIndex">
<CascadingValue Value="@CascadingName">
<SecondComponent></SecondComponent>
</CascadingValue>
</CascadingValue>
@code {
int CascadingIndex = 10000;
string CascadingName = "FirstComponent";
}
SecondComponent源码如下:
<h3>SecondComponent</h3>
<p>
CascadingValue Is <strong>@SecondValue</strong>
</p>
@code {
[CascadingParameter] int SecondValue { get; set; }
}
传值的过程中,我们只有一个int类型的属性,所以该值会显示10000,如下图所示:
如果我们修改一下FirstComponent的源码,将其中的string类型的属性删除掉,同时增加一个新的int类型的属性,如下源码所示:运行结果如下:
由此可见,当子组件遇到多个相同类型的属性的时候,会选择离子组件最近的属性的值并传递到自己的属性中去。
命名传值
命名赋值就很单纯了,主要考虑绑定正确的名称就行。修改后FirstComponent的源码如下,需要指定Name
<CascadingValue Value="@CascadingIndex" Name="CascadingIndex">
<CascadingValue Value="@Total" Name="Total">
<SecondComponent></SecondComponent>
</CascadingValue>
</CascadingValue>
@code {
int CascadingIndex{ get; set; } = 10000;
int Total{ get; set; } = 2;
}
SecondComponent源码如下,可以指定名称已接收值的传递
<h3>SecondComponent</h3>
<p>
CascadingValue Is <strong>@SecondValue</strong>
</p>
@code {
[CascadingParameter(Name = "CascadingIndex")] int SecondValue { get; set; }
}
运行后的结果如下,值又变回了10000,
有朋友可能会想,我不想设置SecondComponent中CascadingParameter的Name值,但是我可以设置成FirstComponent中某个已经绑定的Name的名称。如下所示:FirstComponent源码不变,SecondComponent源码如下:
<h3>SecondComponent</h3>
<p>
CascadingValue Is <strong>@Total</strong>
</p>
@code {
[CascadingParameter] int Total { get; set; }
}
运行结果如下所示:
由此可见,不设置子组件中CascadingParameter的Name值,是无法接收传递的值的。
性能问题
默认情况下,Blazor会持续监控级联值的变化,并将其传递到所有子组件中,这将会占用一定的资源,并可能导致性能问题。如果我们可以确定,我们的级联值不会发生变化,可以设置CascadingValue中参数IsFixed的值为true,这样的Blazor就不会监控级联值的变化了。
<CascadingValue Value="@CascadingIndex" IsFixed="true">
<SecondComponent></SecondComponent>
</CascadingValue>
- 如何通过追踪代码自动发现网站之间的“关联”
- 教你如何和使用这款强大的渗透平台-Xerosploit
- No.014 Longest Common Prefix
- Java实现解析IP地址的方法,给出一串数字,生成正确的IP地址
- 图解“管道过滤器模式”应用实例:SOD框架的命令执行管道
- No.013 Roman to Integer
- OData – the best way to REST–实例讲解ASP.NET WebAPI OData (V4) Service & Client
- Java实现的手工做乘法方法,给出二个字符串数字,返回相乘结果
- No.012 Integer to Roman
- 黑帽SEO剖析之手法篇
- IOS学习1——IOS应用程序的生命周期及基本架构
- 浅议“全局变量”、“多线程”和“编译器陷阱”
- Java实现的图片合并方法,支持水平和垂直合并
- OC学习15——文件I/O体系
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 单词搜索
- JVM运行时数据区
- 最长重复子数组
- 编辑距离
- 有序矩阵中第K小的元素
- nodejs库yaml读取yml或yaml配置文件
- 爬虫小白:03.requests的使用
- Oracle GoldenGate 19 Microservices数据同步实战与故障处理
- 给“小白”漫画+图示讲解MyBatis原理,就问香不香!
- webClientTest 编写单元测试类
- 关于gorm多表联合查询(left join)的小记
- UnicodeEncodeError: 'latin-1' codec can't encode character 'u2026' in position 30: ordinal not i...
- Oracle GoldenGate 19 Microservices完整高可用安装、配置与测试
- 爬虫小白:11.scrapy框架(六) _媒体管道
- R基于TCGA数据画生存曲线