Blazor学习之旅(4)数据共享
本篇,我们来了解下在Blazor中数据是如何共享的,组件之间又该如何传递参数。
关于Blazor组件
在 Blazor 中,从名为“组件”的自包含代码部分生成 UI。每个组件都可以包含 HTML 和 C# 代码的混合。组件是通过使用 Razor 语法编写的,其中的代码是用 @code 指令标记的。其他指令可用于访问变量、绑定到值以及实现其他呈现任务。
编译应用时,HTML 和代码将编译为组件类。组件一般被编写为扩展名为 .razor 的文件。
关于数据共享
Blazor 包含多种在组件之间共享信息的方法。
(1)可使用组件参数或级联参数将值从父组件发送到子组件。
(2)AppState 模式是另一种可用于存储值并从应用程序中的任何组件访问这些值的方法。
使用组件参数共享
在父组件和子组件的此层次结构中,可以使用组件参数在它们之间共享信息。在子组件上定义这些参数,然后在父组件中设置其值。
例如,在Counter组件中,定义了一个IncrementAmount的组件参数:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
[Parameter]
public int IncrementAmount { get; set; } = 1;
private void IncrementCount()
{
currentCount += IncrementAmount;
}
}
在调用端只需要下面这样既可,由于Counter组件中还设置了默认值为1,因此,如果调用端不传递,则默认为1。
<Counter IncrementAmount="10" />
此外,还可以使用自定义类用作组件参数,例如:
@using EDT.BlazorServer.App.Models <p>New Topping: @Topping.Name</p>
<p>Ingredients: @Topping.Ingredients</p> @code {
[Parameter]
public PizzaTopping Topping { get; set; }
}
PizzaTopping的定义如下:
public class PizzaTopping
{
public string Name { get; set; }
public string Ingredients { get; set; }
}
调用方的定义如下:
@page "/pizzas-toppings"
<h1>Our Latest Pizzas and Topping</h1>
<PizzaTopping Topping="@(new PizzaTopping() { Name = "Chilli Sauce", Ingredients = "Three kinds of chilli." })" />
使用级联参数共享
当具有包含子组件的子组件的较深层次结构时,事情便会变得难以应付。组件参数不会从上级组件或沿着层次结构向下自动传递到下级组件。为了完美处理此问题,Blazor 包含了级联参数。在组件中设置级联参数的值时,其值将自动提供给所有子组件。
在父组件中,使用 标记指定将级联到所有子组件的信息。此标记作为内置的 Blazor 组件实现。在该标记内呈现的任何组件都将能够访问该值。
例如,我们有三个组件,其中,CascComp2组件被嵌套在CascComp1组件中,而CascComp1组件又被嵌套在CascCompSamle组件中。他们的调用关系如下:

使用CascadingParameter级联传递参数NickName:
(1)CascCompSample.razor
<!--this is CascCompSample.razor--> @page "/cascparamsample" <h3>This is the sample page</h3> <CascadingValue Value="NickName">
<CascComp1></CascComp1>
</CascadingValue> @code
{
private string NickName = "Edison Zhou";
}
(2)CascComp1.razor
<!--this is CascComp1.razor-->
<h3>Comp1: @NickName</h3>
<CascComp2></CascComp2>
@code {
[CascadingParameter]
public string NickName { get; set; }
}
(3)CascComp2.razor
<!--this is CascComp2.razor-->
<h3>Comp2: @NickName</h3>
@code {
[CascadingParameter]
public string NickName { get; set; }
}
要点:
(1)首先在CascCompSample.razor页面,我们通过把CascComp1嵌套到CascadingValue里面来传递参数。
(2)其次在CascComp1和 CascComp2,不再需要显式传递参数,只需要声明CascadingParameter即可拿到值。
效果:

如果需要级联传递多个参数,可以使用CascadingValue的嵌套,这里我们修改一下CascCompSample.razor组件,让它可以共享两个参数:
<!--this is CascCompSample.razor--> @page "/cascparamsample" <h3>This is the sample page</h3> <CascadingValue Value="currentNickName" Name="NickName">
<CascadingValue Value="currentAge" Name="Age">
<CascComp1></CascComp1>
</CascadingValue>
</CascadingValue> @code
{
private string currentNickName = "Edison Zhou";
private int currentAge = 34;
}
修改CascComp1.razor,增加一个CascadingParameter属性Age:
<!--this is CascComp1.razor-->
<h3>Comp1: @NickName - @Age</h3>
<CascComp2></CascComp2>
@code {
[CascadingParameter(Name="NickName")]
public string NickName { get; set; }
[CascadingParameter(Name="Age")]
public int Age { get; set; }
}
CascComp2.razor修改同上,不再赘述。
这里需要注意的是:级联值由父级中的 Name 属性标识,与 [CascadingParameter] 属性中的 Name 值匹配。对于只有一个该类型的参数而言,在子组件中CascadingParameter特性中无需指定Name。但对于如果有多个相同类型的级联参数而言,最好加上Name名称进行指定,以避免找不到。因此,这里也推荐在CascadingValue中指定Name,然后再CascadingParameter特性中指定Name。
最终效果:

使用AppState模式共享
在不同组件之间共享信息的另一种方法是使用 AppState 模式。
即创建一个定义要存储的属性的类,并将其注册为作用域服务。在要设置或使用 AppState 值的任何组件中,注入该服务,然后可以访问其属性。不同于组件参数和级联参数,AppState 中的值可用于应用程序中的所有组件,即使这些组件不是存储该值的组件的子组件也是如此。
例如,创建一个包含销售状态的类:
public class PizzaSalesState
{
public int PizzasSoldToday { get; set; }
}
然后,将该类注入到DI容器中:
builder.Services.AddScoped<PizzaSalesState>();
最后,在任意组件中通过依赖注入来访问该属性:
@page "/"
@using EDT.BlazorServer.App.Models
@inject PizzaSalesState salesState; <PageTitle>Index</PageTitle> <h1>Hello, world!</h1> Welcome to your new app. <SurveyPrompt Title="Your Pizza Shop" /> @*<Counter IncrementAmount="10" />*@
<p>Today, we've sold this many pizzas: @salesState.PizzasSoldToday</p>
<button @onclick="IncrementSales">Buy a Pizza</button> @code {
private void IncrementSales()
{
salesState.PizzasSoldToday++;
}
}
在本例中,由于我们已将计数器的值存储在 AppState 范围内服务中,因此计数会在页面加载期间一直存在,并且对其他用户可见。
最终效果:

小结
本篇,我们了解了数据如何在Blazor中共享。
下一篇,我们学习一下在Blazor中数据绑定的各种花样。
参考资料
Microsoft Docs,《在Blazor应用程序中共享数据》
65号腕,《Blazor中的参数和级联参数》

Blazor学习之旅(4)数据共享的更多相关文章
- WCF学习之旅—第三个示例之四(三十)
上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) WCF学习之旅—第三个示例之三(二十九) ...
- Hadoop学习之旅二:HDFS
本文基于Hadoop1.X 概述 分布式文件系统主要用来解决如下几个问题: 读写大文件 加速运算 对于某些体积巨大的文件,比如其大小超过了计算机文件系统所能存放的最大限制或者是其大小甚至超过了计算机整 ...
- WCF学习之旅—第三个示例之二(二十八)
上接WCF学习之旅—第三个示例之一(二十七) 五.在项目BookMgr.Model创建实体类数据 第一步,安装Entity Framework 1) 使用NuGet下载最新版的Entity Fram ...
- WCF学习之旅—第三个示例之三(二十九)
上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) 在上一篇文章中我们创建了实体对象与接口协定,在这一篇文章中我们来学习如何创建WCF的服务端代码.具体步骤见下面. ...
- WCF学习之旅—WCF服务部署到IIS7.5(九)
上接 WCF学习之旅—WCF寄宿前的准备(八) 四.WCF服务部署到IIS7.5 我们把WCF寄宿在IIS之上,在IIS中宿主一个服务的主要优点是在发生客户端请求时宿主进程会被自动启动,并且你可以 ...
- WCF学习之旅—WCF服务部署到应用程序(十)
上接 WCF学习之旅—WCF寄宿前的准备(八) WCF学习之旅—WCF服务部署到IIS7.5(九) 五.控制台应用程序宿主 (1) 在解决方案下新建控制台输出项目 ConsoleHosting.如下 ...
- WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)
上接 WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...
- WCF学习之旅—WCF服务的WAS寄宿(十二)
上接 WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) 八.WAS宿主 IIS ...
- WCF学习之旅—WCF服务的批量寄宿(十三)
上接 WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) WCF学习之旅—WCF ...
- WCF学习之旅—第三个示例之五(三十一)
上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) WCF学习之旅—第三个示例之三(二十九) WCF学习 ...
随机推荐
- 在 PHP 中,原生并没有提供内置的定时器机制,定时触发的守护进程,其中一个常见的方式是使用循环和时间戳来检查触发时间。自定义事件触发
<?php class TimerDaemon { private $logfile; private $fp; private $triggerInterval; // 触发间隔,以秒为单位 ...
- Golang 获取类型
可以通过reflect包的TypeOf()取得某一变量或值的类型.
- 《Python基础教程》第三版语录
对程序的结构(如需要哪些类和函数)有一定的想法后,建议你实现一个功能可能极其有限的简单版本. 当你有了可运行的程序后,将发现接下来的工作容易得多.你可添加新功能,修改不喜欢的方面,等等.这样你才能够真 ...
- SQL语句执行慢情况
排查历史慢查询: SELECT TOP 20 [Total IO] = (qs.total_logical_reads + qs.total_logical_writes) , [Average IO ...
- Cloud Native CI/CD: tekton and argocd
https://platform9.com/blog/argo-cd-vs-tekton-vs-jenkins-x-finding-the-right-gitops-tooling/ implemen ...
- zk源码—4.会话的实现原理
大纲 1.创建会话 (1)客户端的会话状态 (2)服务端的会话创建 (3)会话ID的初始化实现 (4)设置的会话超时时间没生效的原因 2.分桶策略和会话管理 (1)分桶策略和过期队列 (2)会话激活 ...
- Spring框架中的单例bean是线程安全的吗?
1.介绍两个概念 有状态的bean:对象中有实例变量(成员变量),可以保存数据,是非线程安全的 无状态的bean:对象中没有实例变量(成员变量),不能保存数据,可以在多线程环境下共享,是线程安全的 2 ...
- web自动化:webdriver常用api
一.获取操作 1.get('url'):访问指定的url webdriver.get(String url); 2.Getcurrenturl():获取当前页面url webDriver.getCur ...
- Windows-exporter(node-exporter)+ Prometheus + Grafana资源监控搭建
在性能测试过程中,资源监控可以时刻掌握被测软件运行环境的各类数据,从而更加直观地反馈测试过程中潜在的问题,下面是基于Windows-exporter(node-exporter)+ Prometheu ...
- kubeadm部署高可用master
准备阶段 master1 master2 master3 node1 关闭selinux,firewall setenforce 0 sed -i 's/SELINUX=enforcing/SE ...