翻译自:Study Blazor .NET,转载请注明。
数据绑定
单向绑定
在blazor中单向绑定简单而直接,无需UI刷新或渲染。下面示例展示了单向数据绑定:
//Counter.razor
@page "/counter"
Counter
Current count: @currentCount
@functions {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
}
}
这里 @currentComponent
的值会根据点击 Click me
按钮的次数而增加。 标签元素的值会自动刷新无需任何其它组件刷新。
双向绑定
Blazor为双向绑定提供多种选择,与一些流行的JS语言相比实现起来更加优雅。
相同组件中使用绑定
在blazor中,bind
特性支持双向数据绑定,在下面的例子中,checkbox 在同一个组件中使用了 bind
属性:
//TwoWayBind.razor
@page "/two-way-binding"
This string will get value from above text field : @updateString.ToString()
@functions {
Boolean updateString {get; set;} = true;
}
双向数据绑定也能用lamda表达式通过 onchange
特性实现。不用担心,Blazor提供了绑定属性的简单方法,更多细节如下:
//TwoWayBind.razor
@page "/two-way-binding"
This string will get value from above text field: @updateString
@functions {
string updateString = "";
}
bind
特性可以使用值和事件 bind-value-
进行扩展,上面的示例可以用 oninput
代替 onchange
重写如下:
//TwoWayBind.razor
@page "/two-way-binding"
This string will get value from above text field : @updateString
@functions {
string updateString = "";
}
不同组件间使用绑定
方法 1
组件之间传递的数据通过组件属性及其属性映射完成,这种方法使用 Action
数据类型。
//ParentComponent.razor
Parent Component
String in Parent: @parentString
@functions{
private string parentString = "Initial Parent String";
private void PassToChild()
{
parentString += "- To Child";
}
private void ReceivedFromChild(string str)
{
parentString = str;
StateHasChanged();
}
}
//ChildComponent.razor
Child Component
String received from Parent : @ToChild
@functions{
[Parameter]
private string ToChild{get;set;}
[Parameter]
Action FromChild{get;set;}
private string childString;
private void PassToParent()
{
childString = ToChild + "- To Parent";
FromChild(childString);
}
}
ChildComponent中的 FromChild
特性/属性用 Action
类型从子组件向父组件传递值。在父组件中有一个带有 string
类型参数的响应函数,ChildComponent组件中的按钮点击操作触发这个函数,并且反过来通知 PassToParent
函数,为了通知父组件中的状态已经改变,我们使用了Blazor内置函数 StateHasChanged()
。
方法 2
这种方法使用 EventCallback
数据类型指定事件变更来传递信息从而代替具体的数据,这里不需要再调用 StateHasChanged()
函数。
//ParentComponent.razor
Parent Component
Logging Event triggered from Child: @logString
@functions{
private string logString = "";
private void TriggerFromChild(UIMouseEventArgs e)
{
logString = e.ToString();
}
}
//ChildComponent.razor
Child Component
@functions{
[Parameter]
private EventCallback Trigger { get; set; }
}
在ChildComponent中,Trigger
属性回调ParentComponent中相应的带有 UIMouseEventArgs
参数的TriggerFromChild
方法,同时在父组件中以字符串形式记录。
下面是支持的事件参数:
- UIEventArgs
- UIChangeEventArgs
- UIKeyboardEventArgs
- UIMouseEventArgs
方法 3
这里是组件间双向绑定的另一种方法,我们可以基于任何事件/方法的执行手动触发一个 Action
,
//ParentComponent.razor
Parent Component
Logging Event triggered from Child: @logString
@functions{
private string logString = "";
private void TriggerFromChild()
{
logString = "Triggered From Child using Action and Invoke";
StateHasChanged();
}
}
//ChildComponent.razor
Child Component
@functions{
[Parameter]
private Action EventFromChild{get;set;}
private void Trigger()
{
EventFromChild?.Invoke();
}
}
在ChildComponent中,用内置函数 Invoke
手动触发 EventFromChild
Action 属性,同时回调父组件中相应的 TriggerFromChild
方法,在父组件中,通过 StateHasChanged()
通知状态已经改变。
级联值和参数
Blazor提供了一种跨越整个RenderTree(所有组件)传递数据的方法,使用 CascadingValue
和 CascadingParameter
代替传递组件特性。传递的值可以被RenderTree (子组件)通过装饰属性 CascadingParameter
代替 Parameter
接收。
//RootComponent.razor
@page "/base-component"
App Base Component
@functions {
private string pName {get;set;} = "New To Blazor";
private int pAge {get;set;} = 35;
}
//ParentComponent.razor
Parent Component
Profile Name is : @Name and Age is : @Age.ToString();
@functions{
[CascadingParameter(Name = "ProfileName")]
string Name { get; set; }
[CascadingParameter(Name = "ProfileAge")]
int Age {get;set;}
}
在 CascadingParameter
中,Name
参数必须与具有 CascadingValue
组件的 Name
属性匹配,如果我们没有声明 Name
,那么 CascadingParameter
中的变量类型与 CascadingValue
中的 Value
属性匹配。
最好声明 Name
参数,以避免混淆,这在应用程序规模增长时很有用。
渲染片段,动态内容
除了用特性从父组件向子组件传递内容,还可以在组件的 tag 元素中传递内容,并且可以使用 RenderFragment
属性在子组件中呈现。
方式 1
ChildContent
是我们需要在子组件中使用的命名约定,以获取父组件的内容,
//ParentComponent.razor
Parent Component
The line here is passed to child from Parent!!!
//ChildComponent.razor
Child Component
@ChildContent
@functions{
[Parameter]
private RenderFragment ChildContent { get; set; }
}
方式 2
RenderFragment
主要用于模板化目的,并基于子组件内部的逻辑呈现内容。
//ParentComponent.razor
Parent Component
Bold Text here!!!
//ChildComponent.razor
Child Component
@for(var i = 1; i <= 3; i++)
{
Line No : @i
@SampleText
}
@functions{
[Parameter]
private RenderFragment SampleText { get; set; }
}
此时 SampleText
不是已经存在的组件,它是在父组件中的 ChildComponent
tag元素中新生成的,同时在子组件中也声明了相同的命名为 SampleText
的属性。
SampleText
中的文本在子组件里循环渲染3次,这非常有助于创建模板组件、表格等。