Skip to main content

Blazor组件基础之数据绑定

分类:  Blazor入门 标签:  #Asp.Net core基础 #.Net #Web #Web Client #Blazor 发布于: 2023-05-27 10:11:37

今天我们来学习组件的数据绑定。

提起数据绑定我相信很多windows的老粉都应该非常熟悉了,对于数据绑定这个概念只要学习过windows的编程的都不陌生,这也是微软在设计软件系统的一个非常大的特定,所有有UI的软件都有数据绑定的概念,对于Blazor来说,也不例外。

Blazor组件的数据绑定很简单,只需要在组件中的元素中使用类HTML 属性的方式:@bind 将该元素的值和字段,属性,或者是Razor表达式绑定到一起。绑定的意思我们需要在这里加深理解,也即该元素绑定的值和在@code {} 或者部分类中定义的字段/属性/Razor 表达式是紧密相关的,加入字段或者属性的值改变,那么该元素的值也跟着改变,如下图:



从图中可以看出将组件中的元素值绑定到属性,或者字段非常容易,只需要使用@bind属性就可以了。同时我们还特定使用了Razor表达式将该属性的值输出,在测试该代码你会发现,在文本框中输入了新的之后,只有文本框失去焦点,属性值才会被更新,可以从Razor的表达式输出直接观察到。

这里引发另外一个思考:实际上数据绑定也就是相当于在元素<input />上绑定了一个onChange事件,在文本框里输入了数值,然后失去焦点之后,onchange中的代码会更新属性值,当然实际生成的代码肯定比这个更复杂,因为@bind属性还考虑了类型转换的问题。

实际上Blazor框架中默认的数据绑定就是和onchange事件相关联,也就是数据绑定不仅仅同时有一个隐形的事件同时会发生,默认是onchange事件,也就是组件中的元素失去焦点后会触发更改。

那么有没有可能使用其他的事件进行绑定呢?答案是有的,可以使用如下的格式:

<input @bind="属性名" @bind:event={事件名} /> 将数据绑定到其他的事件上。

例如:



会发现只要在文本框中输入,属性也会跟着更新,而不是像之前在文本框里输入文字完成之后,要失去焦点才会对属性的值进行更新。

由于我们的字段和属性都是强类型,加入用户输入了一个不能被转换的值,Blazor该如何做呢?Blazor会恢复到更改之前的值例如我们将上例属性改为int, 然后尝试输入字符串:



最佳实践:

  • 不建议在绑定中使用oninput事件,而是缺省使用onchange事件。

  • 如果绑定了一个可空值类型(int? 或者string )需要添加自定义的逻辑进行判断。

  • 使用EditContext 提示用户输入错误。

  • 使用表单验证来处理大量的输入。这个部分请参考后继表单验证的部分。

 

格式化输出

Blazor目前仅仅支持对于DateTime类型进行格式化输出,定义如下:


支持的类型也仅仅包括:

System.DateTime

System.DateTime?

System.DateTimeOffset

System.DateTimeOffset?

 

绑定组件参数 

我们除了可以通过指令@bind绑定属性,字段以及Razor表达式之外,我们还可以将子组件中的属性和父组件的属性绑定在一起。我们称之为链接绑定(chained bind),

组件参数通过如下的形式来绑定父组件的属性:@bind-{Property Name}的形式来绑定。

上面我们学习到通过@bind来绑定的话,实际上除了绑定属性,还有一个默认的onchange事件发生,但是在通过@bind来绑定的话,无需定义这个事件,但是通过组件参数来绑定父组件中的属性,不能使用和@bind一样的语法,必须除了绑定,还需要重新定义一个事件的call 方法来从子组件中更新父组件中的属性。

 Tips:  事件callback 方法的定义名字是有要求的,必须是组件参数的名字加上"Changed" 作为完整的函数名。

 如下是子组件的定义:

Child.razor


我们接下来看看父组件中怎么将自己的属性和子组件绑定的:


通过上图可以看到在父组件中调用子组件的时候,通过@bind-{子组件参数} = {父组件属性,字段} 进行了绑定。

 

但是这里有一个问题:

我们注意到子组件中定义了两个参数啊。一个是属性 Year, 一个是一个EventCallBack<int> 的delegate, 是吗?那我们在调用组件的时候,并没有显式的定义这个参数啊。为什么呢?

这是因为我们一开始就讨论过,@bind 除了绑定值,默认还有一个事件的,那就是onchange,所以这里实际上是将父组件的onchange事件附给了子组件的EventCallBack delegate 。

 

现在在父组件中可以更新子组件的属性,也可以在子组件中更新父组件的字段,并且同时渲染。

同时您可以使用这个特性绑定多个组件,但是这里有一个重要的推荐,那就是最好在更高级别的组件向子组件绑定属性,例如:Parent.razor -> firstChild.razor -> secondlyChild.razor. 这样的数据流动方向。

我建议大家可以将这个特性和级联值级联参数做一个对比,发现很有趣,级联值只能静态的传递值,但是组件参数绑定(链接绑定)除了可以传递数据还可以传递方法, 会进行动态的更新。这个是一个非常好的特性。


这是上述的例子结果图,点击父组件或者是子组件的按钮,都会同时更新。