哈Ha!
因此,是的,net core 3.0即将推出,并且将有一个项目模板,其中Blazor是默认模板之一。 在我看来,该框架的名称类似于某些Pokemon的名称。 开拓者开始战斗! 我决定看一下它是哪种动物,以及它被吃什么,所以我在上面制作了一个待办事项表。 好吧,也可以在Vue.js上与主题进行比较,因为在我看来,它们在组件和反应性方面都类似于组件系统,仅此而已。 更多女神神灵! 实际上,这是一个指南,面向那些懒于学习TypeScript或JavaScript并且想要在网站上进行按钮和输入的懒惰的年轻人。 就像那个模因一样-“这位技术人员想写一本书,但指示却出来了。” 谁对我在前端的冒险感兴趣,或者发现欢迎您使用哪种Blazor。
引言
微软曾经有过在浏览器中使用C#的想法,并将其称为Silverlight。 它没有起飞。 然后,您的这些tyrnet与实际的浏览器有所不同。 我为什么认为它现在正在起飞? 因为现在默认情况下,Web程序集在所有现代浏览器中都可用。 无需安装单独的扩展。 另一个问题是应用程序大小。 如果Vue.js SPA的重量为1.7兆字节,那么Blazor的21兆字节完全相同。 现在,Internet变得比Silverlight时代更快,更可靠,您需要下载一次应用程序,然后就可以拥有缓存和所有内容。 通常,Blazor看起来与Vue.js非常相似。 因此,为了向Silverligtht,WPF和UWP致敬,并且因为在Sharper中如此普遍,我决定在项目中使用MVVM模式。 因此,仅供参考-我通常是后端,我喜欢Blazor。 我警告我-例子中的设计和布局非常糟糕,在使用Vue.js的项目中,经验丰富的前端作家可以看到很多govnokod。 好吧,有了拼写和标点符号,事情也就这样。
参考文献
Vue + Vuex上的Todo示例Blazor上的Todo示例展示位置模型
- 在客户端。 可以以多种方式分发的标准SPA。 在我的示例中,我使用了一个模板,在其中将应用程序文件发送到asp.net核心上的浏览器服务器。 这种方法的缺点是需要下载到浏览器的那21兆字节。
- 在服务器端。 一切都在服务器上发生,完成的DOM通过套接字传递给客户端。 浏览器一开始根本不需要下载任何东西,而是不断地分段下载更新的DOM。 好吧,客户端代码的全部负载突然落到了服务器上。
我个人更喜欢第一种选择,并且可以在不需要担心用户转换的所有情况下使用。 例如,这是公司的某种内部信息系统或专用的B2B解决方案,因为Blazor首次下载已很长时间。 如果您的用户不断登录到您的应用程序,那么他们将不会注意到与JS版本的任何区别。 如果用户单击广告链接,则只需查看那里的网站类型,很可能他不会等待很长时间就可以加载并离开网站。 在这种情况下,最好使用第二个放置选项,即 服务器端西装外套
项目创建
下载Net Core 3.0
dotnet.microsoft.com/download/dotnet-core/3.0在终端中运行命令,该命令将为您加载必要的模板。
dotnet new -i Microsoft.AspNetCore.Blazor.Templates
创建服务器端
dotnet new blazorserverside -o MyWebApp
对于客户端,其文件将由asp.net核心服务器分发
dotnet new blazorhosted -o MyWebApp
如果您想了解异国情调并突然决定不将asp.net core用作服务器,则可以使用其他命令(是否完全需要它?),使用此命令只能创建一个没有服务器的客户端。
dotnet new blazor -o MyWebApp
绑定
支持单向和双向绑定。 因此,是的,您不需要像WPF中的任何OnPropertichanged。 更改视图模型时,布局会自动更改。
<label>One way binding:</label> <br /> <input type="text" value=@Text /> <br /> <label>Two way binding:</label> <br /> <input type="text" @bind=@Text /> <br /> <label>Two way binding Text oninput:</label> <br /> <input type="text" @bind=@Text @bind:event="oninput" />
因此,这里有一个具有Text字段的ViewModel(匿名)。
在第一个输入中,通过“ value = @ Text”,我们进行了单向绑定。 现在,当我们在代码中更改文本时,输入中的文本将立即更改。 只有这样我们才能在输入中不进行打印,这才以任何方式影响我们的VM。 在第二个输入中,通过“ @ bind = @ Text”,我们进行了双向绑定。 现在,如果我们在输入中编写新内容,我们的VM将立即更改,反之亦然,即 如果我们更改代码中的“文本”字段,那么我们的输入将立即显示新值。 有一个BUT-默认情况下,更改与输入的onchange事件相关,因此VM仅在完成输入后才会更改。 在第三个输入“ @bind:event =” oninput“”中,我们现在每次将某些字符打印到新值时,都会将用于将VM数据传输到oninput的事件更改为oninput。 例如,您还可以指定DateTime的格式。
<input @bind=@Today @bind:format="yyyy-MM-dd" />
查看模型
您可以将其设为匿名,然后需要在“ @code {}”块中将其停止
@page "/todo" <p> @UserName </p> @code{ public string UserName{get; set;} }
或者您可以将其放在单独的文件中。 然后必须从ComponentBase继承它,并在页面顶部使用“ @inherits”指定指向我们的VM的链接
举个例子
TodoViewModel.cs:
public class TodoViewModel: ComponentBase{ public string UserName{get; set;} }
Todo.razor:
@page "/todo" @inherits MyWebApp.ViewModels.TodoViewModel <p> @UserName </p>
路由选择
在页面的开头使用“ @page”指示页面将响应的路由。 而且,可能有几个。 将按照从上到下的顺序选择完全匹配的第一个。 例如:
@page "/todo" @page "/todo/delete" <h1> Hello!</h1>
此页面将以“ / todo”或“ todo / delete”打开
版面
通常,通常在几页上放置相同的内容。 像侧边栏,等等。
为了首先使用布局,您需要创建它。 必须使用“ @inherits”从LayotComponentBase继承。 举个例子
@inherits LayoutComponentBase <div class="sidebar"> <NavMenu /> </div> <div class="main"> <div class="top-row px-4"> <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a> </div> <div class="content px-4"> @Body </div> </div>
其次,它需要导入。 为此,在包含使用它的页面的目录中,您需要创建_imports.razor文件,然后在该文件中添加“ @layout”行
@layout MainLayout @using System
第三,您可以在页面上指示其直接使用哪种布局
@layout MainLayout @page "/todo" @inherits BlazorApp.Client.Presentation.TodoViewModel <h3>Todo</h3>
通常,_imports.razor及其在其中使用会作用于与它位于同一文件夹中的所有页面。
路线选项
首先,在我们的路线中,使用大括号表示参数及其类型(不区分大小写)。 支持标准类型。 所以是的,没有可选参数,即 值必须始终传递。
可以通过在ViewModel中创建一个与参数同名的属性并使用[Parameter] BTB属性来获取值本身-之前已经遇到过-父组件中的数据和事件也可以使用[Parameter]属性以及级联参数从父组件中传输。 它们从父组件传递到其所有子组件及其子组件。 它们主要用于样式,但是最好只使用CSS样式,所以为什么不在乎。
@page "/todo/delete/{id:guid}" <h1> Hello!</h1> @code{ [Parameter] public Guid Id { get; set; } }
DI
与常规asp.net核心应用程序一样,所有内容都在Startup.cs中注册。 这里没有新内容。 但是,我们的VM依赖关系的实现仍然通过公共属性而不是通过构造函数进行。 该属性只需用[Inject]属性装饰
public class DeleteTodoViewModel : ComponentBase { [Parameter] private Guid Id { get; set; } [Inject] public ICommandDispatcher CommandDispatcher { get; set; }
默认情况下,已经连接了3个服务。 HttpClient-好吧,你知道为什么。 IJSRuntime-从C#调用JS代码。 IUriHelper-使用它无法重定向到其他页面。
应用实例
Todo电子表格
TodoTableComponent.razor:
- 由于此组件,我们不需要“ @page”和“ @layout”,因为它不会参与路由,并且会使用父组件的布局
- C#代码以@符号开头。 其实和剃刀一样
@onclick=@(()=>ClickRow(item.Id))
将行单击事件绑定到我们的ViewModel的ClickRow方法- 使用[Parameter]属性指定哪些参数将从父组件或页面转移到我们的组件或页面
- 我们调用从父组件收到的回调函数。 因此,父组件得知孩子中发生了一些事件。 函数只能包装在EventCallback <>参数化的EventArgs中传递。 可在此处找到EventArgs的可能列表-docs.microsoft.com/ru-ru/aspnet/core/blazor/components?view=aspnetcore-3.0#event-handling
- 由于EventArgs可能类型的列表是有限的,并且我们需要将附加的Id属性传递给父组件一侧的事件处理程序,因此我们创建了从基类继承的自己的参数类,并将其传递给事件。 是的,在父组件中,常规UIMouseEventArgs将进入事件处理程序的函数,并且需要将其转换为我们的类型,例如,使用as运算符
用法示例:
<TodoTableComponent Items=@Items OnClick=@Select Current=@(Selected?.Id??Guid.Empty)></TodoTableComponent>
待办事项删除页面
我们的ViewModel aka VM是DeleteTodoViewModel.cs:
public class DeleteTodoViewModel : ComponentBase {
- 路由参数“ / todo / delete / {id:guid}”在此处传递给Guid,例如,如果传递到localhost / todo / delete / ae434aae44 ...
- 将服务从DI容器注入到我们的VM中。
- 只是我们VM的一个属性。 我们可以根据需要自行设置其值。
- 初始化页面后,将自动调用此方法。 在这里,我们为VM的属性设置必要的值
- 我们的VM的方法。 例如,我们可以将其绑定到单击视图的任何按钮的事件上
- 转到位于“ / todo”地址的另一页,即 她在行首有“ @page” /“ todo”
我们的视图是DeleteTodo.razor:
- 我们指示该国家/地区的地址为{我们网站的根地址} +“ / todo / delete /” + {某种Guid}。 例如localhost / todo / delete / ae434aae44 ...
- 指定我们的页面将在MainLayout.razor中呈现
- 指定我们的页面将使用DeleteTodoViewModel类的属性和方法
- 我们缩小范围,当您单击此按钮时,将调用我们虚拟机的Delete()方法
待办事项首页
TodoViewModel.cs:
public class TodoViewModel : ComponentBase { [Inject] public ICommandDispatcher CommandDispatcher { get; set; } [Inject] public IQueryDispatcher QueryDispatcher { get; set; }
- 支持System.ComponentModel.DataAnnotations中的标准验证属性。 具体来说,在这里我们指示此字段是必填字段,并且如果用户未在输入中指定与该字段关联的值,则将显示该文本。
- 使用参数处理事件的方法。 此方法将处理子组件中的事件。
- 我们将参数转换为我们在子组件中创建的类型
Todo.razor:
@layout MainLayout @page "/todo" @inherits BlazorApp.Client.Presentation.TodoViewModel <h3>Todo</h3> <h4></h4> <div class="row"> <div class="col"> @if (Items == null) { <p><em>...</em></p> } else if (Items.Count == 0) { <p><em> . .</em></p> } else {
- 我们调用子组件并将其VM的属性和方法作为参数传递给它。
- 带有数据验证功能的内置表单组件。 我们在其中指出,作为模型,他将使用我们的VM,并在发送有效数据时将调用其Create()方法
- 将使用[Requared]等模型属性执行验证。
- 在这里,我将显示验证的一般错误
- 将创建带有验证的输入。 可能的标签列表为InputText,InputTextArea,InputSelect,InputNumber,InputCheckbox,InputDate
- 公共字符串属性NewTodo {get; set;}的验证错误将在此处显示
- 当您单击此按钮时,将引发我们表单的OnValidSubmit事件
Startup.cs文件
在这里我们注册我们的服务
public class Startup { public void ConfigureServices(IServiceCollection services) {
结语
写这篇文章是为了胃口,并鼓励进一步研究Blazor。 我希望我实现了我的目标。 好吧,为了更好地研究它,我建议阅读Microsoft的官方手册 。
致谢
感谢AndreyNikolin , win32nipuh和SemenPV在文本中发现的拼写和语法错误。