开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

您所在的位置:网站首页 blazor教程 开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

#开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor| 来源: 网络整理| 查看: 265

? @H_598_301@ 1 2 3 4 5 6 7 @ using System.Net.Http @ using Microsoft.AspNetCore.Blazor @ using Microsoft.AspNetCore.Blazor.Components @ using Microsoft.AspNetCore.Blazor.Layouts @ using Microsoft.AspNetCore.Blazor.Routing @ using BlazorDemo @ using BlazorDemo.Shared

 

Program.cs是程序的入口点

using Microsoft.AspNetCore.Blazor.Browser.Rendering; using Microsoft.AspNetCore.Blazor.Browser.Services; using System; namespace BlazorDemo { class Program { static void Main(string[] args) { var serviceProvider = new BrowserServiceProvider(configure => { // Add any custom services here }); new BrowserRenderer(serviceProvider).AddComponent("app"); } } }

在入口点中,我们注册了一个浏览器渲染服务 BrowserRender,让他渲染App

App.cshmtl是这样的

这里的Router对应的是Microsoft.AspNetCore.Blazor.Routing.Router. 当给它一个AppAssembly时,他就会自动的把当前的Url 和 AppAssembly的其他Pages对应起来.

所以 当我们在浏览器里输入 /Counter时,他就会加载Pages/Couter.cshtml.

Shared文件夹里分别是布局文件,导航栏,还有一个我们自定义的控件 SurveyPrompt. 

熟悉Razor引擎的小伙伴们一定很轻车熟路了. 那么当我们打开网站时,默认显示给我们的 就是Index,这个时候我们会加载Pages/Index.cshtml

Index.cshtml的代码是这个样子的

@page "/" Hello,world! Welcome to your new app.

@page 可以告诉Router,当前页面注册到 "/"

除了显示hello world以外,我们在这里还看到了刚刚说到的第三方控件. SurveyPrompt. 果然不简单嘛,一个看似简单的页面,居然还告诉了我们如何使用自定义控件.

从声明上看,我们知道 SunveyPrompt是一个控件,并且有一个属性Title. 现在我们打开它的代码

@Title Please take our brief survey and tell us what you think. @functions { // This is to demonstrate how a parent component can supply parameters public string Title { get; set; } }

我们可以看到代码分为两部分,@functions上面是类似html的东西,下面是类似C#的东西. 熟悉React或者Vue的伙伴们恐怕不会对这种混写感到陌生. 这个就是Blazor的语法. Html部分很像使Razor的模板方式. 而最后整个页面都会被编译成一个类,这个类派生自 Component. 如果你编译过项目,你会在Debug下面的Shared目录找到一个叫SurveyPrompt.g.cs的东西

#pragma checksum "/Users/pzhi/SCM/gitHub/zhipu123/BlazorDemo/Shared/SurveyPrompt.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "a2a2ea88635b799343bc6d9647bbb818c8a20c9d" // #pragma warning disable 1591 namespace BlazorDemo.Shared { #line hidden using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Net.Http; using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; using Microsoft.AspNetCore.Blazor.Layouts; using Microsoft.AspNetCore.Blazor.Routing; using BlazorDemo; using BlazorDemo.Shared; public class SurveyPrompt : Microsoft.AspNetCore.Blazor.Components.BlazorComponent { #pragma warning disable 1998 protected override void buildrenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) { base.buildrenderTree(builder); builder.OpenElement(0,"div"); builder.AddAttribute(1,"class","alert alert-survey"); builder.AddAttribute(2,"role","alert"); builder.AddContent(3,"\n "); builder.OpenElement(4,"span"); builder.AddAttribute(5,"glyphicon glyphicon-ok-circle"); builder.AddAttribute(6,"aria-hidden","true"); builder.CloseElement(); builder.AddContent(7,"\n "); builder.OpenElement(8,"strong"); builder.AddContent(9,Title); builder.CloseElement(); builder.AddContent(10,"\n\n Please take our\n "); builder.OpenElement(11,"a"); builder.AddAttribute(12,"target","_blank"); builder.AddAttribute(13,"alert-link"); builder.AddAttribute(14,"href","https://go.microsoft.com/fwlink/?linkid=870381"); builder.AddContent(15,"\n brief survey\n "); builder.CloseElement(); builder.AddContent(16,"\n and tell us what you think.\n"); builder.CloseElement(); builder.AddContent(17,"\n\n"); } #pragma warning restore 1998 // This is to demonstrate how a parent component can supply parameters public string Title { get; set; } } } #pragma warning restore 1591

我们发现@functions里面的内容 会作为这个类的成员变量和 成员方法,而上面的内容则被编译到了buildrenderTree方法中.

那么到了这里我们大概知道了这个简单的HomePage都有什么玄机了. 我们也大概知道了Blazor的语法,也知道其实我们所有的页面最终都会是一个Componet.

那么什么是Componet呢? 在这里并不想过多的去笔墨介绍这个概念. 如果你是一个Vue或者React的开发,你应该对这个模块化开发不陌生. 一个Componet,就是满足一定的功能,有自己的属性,状态. 可以展示特定数据的元素.

就如同我们这里的SurveyPrompt,接受一个Title属性,并且负责把他展示成这样子

分享图片

 数据驱动? Blazor的刷新和绑定机制初探

现在我们知道了一个简单的页面是如何渲染出来的. 那么让我们打开Counter这个配置来看一看. 数据是如何交互的

我们第二个page张这样子

分享图片

有一个button,大声的叫我们点它. 当我们点击的时候. 上面的current count 变成了 1

分享图片

 

这一切是怎么发生的呢? 以下是Counter.cshtml的代码

@page "/counter" Counter Current count: @currentCount Click me @functions { int currentCount = 0; void IncrementCount() { currentCount++; } }

 我们看到 这个页面非常简单,我们定义了一个CurrentCount的Field,然后在IncreaseCount方法里给它加一. 一个叫Click me的button标签里 有一个@onclick方法,将IncreaseCount作为参数

Counter.cshtml编译后的代码张这样

 

#pragma checksum "/Users/pzhi/SCM/gitHub/zhipu123/BlazorDemo/Pages/Counter.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "05ad2dd449cbc9f09f8b759e1f06e7eb5e9583b4" // #pragma warning disable 1591 namespace BlazorDemo.Pages { #line hidden using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Net.Http; using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; using Microsoft.AspNetCore.Blazor.Layouts; using Microsoft.AspNetCore.Blazor.Routing; using BlazorDemo; using BlazorDemo.Shared; [Microsoft.AspNetCore.Blazor.Layouts.LayoutAttribute(typeof(MainLayout))] [Microsoft.AspNetCore.Blazor.Components.RouteAttribute("/counter")] public class Counter : Microsoft.AspNetCore.Blazor.Components.BlazorComponent { #pragma warning disable 1998 protected override void buildrenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) { base.buildrenderTree(builder); builder.OpenElement(0,"h1"); builder.AddContent(1,"Counter"); builder.CloseElement(); builder.AddContent(2,"\n\n"); builder.OpenElement(3,"p"); builder.AddContent(4,"Current count: "); builder.AddContent(5,currentCount); builder.CloseElement(); builder.AddContent(6,"\n\n"); builder.OpenElement(7,"button"); builder.AddAttribute(8,onclick(IncrementCount)); builder.AddContent(9,"Click me"); builder.CloseElement(); builder.AddContent(10,"\n\n"); } #pragma warning restore 1998 int currentCount = 0; void IncrementCount() { currentCount++; } } } #pragma warning restore 1591

 

我们看到 @onclick其实在这里就是执行了一个Component的一个方法onclick,顾名思义,当这个Component被点击的时候就被调用. 我们的IncreaseCount被作为参数传给了它,可见onclick会在被点击的时候执行IncreaseCount.

那么问题来了,当我们执行了IncreaseCount方法时,页面怎么会知道要不要刷新? 是刷新整个页面还是刷新所有?

熟悉WPF的同学可能知道,在WPF中如果我们需要让一个viewmodel可以被监听变化,他就需要实现INotifyChanged事件. 那么同样道理,我们的这个IncreaseCount可能也是类似的吗?

然而基于编译后的代码我们可以发现 CurrentCount作为我们Counter这个类的Field,并没有任何机会高速Page自己变化了. 而且这个Field非常普通,也不是什么WPF中的DP,所以到目前为止变化是怎么通知的.并没有一个合理的解释. 后面的时间里我会尝试阅读Blazor的代码搞清楚这件事情. 

第一个问题画个问号,那么第二个问题呢? 

打开浏览器工具,定位到button,再次点击button观察dom的反应.

分享图片

我们看到 在点击Button的时候,button上面的

标签闪动了,说明它被刷新了,而其他标签并没有. 所以局部刷新的功能是有的. 效率问题不用担心了. 

编辑Click me,把他的内容变成 "点击我",再次点击按钮,我们看到还是只有p变,而且button也没有变回原来的内容

分享图片

 

 所以我们知道,这个局部刷新不是简单的拿Dom作比较,肯定是有Virtual Dom的机制在里面.

 

 星星之火,可燎原?

在简单的尝试了Blazor之后,还是很兴奋的. 可以看到Blazor是一个初具规模的产品. 我们C#开发可以用Blazor在今后写前端渲染的网页了! 

我很期望这样一个产品能够持续的演进下去.

就目前版本看(0.1.0),Blazor尚不能应用到产品中. 主要还是有以下的原因

 打包大小太大,1.8M的大小对于网站简直是致命的.  产品还不成熟,现在Component还只能支持简单的事件,笔者测试的时候只有onclick,onchange.   兼容性差,使用了WebAssembly,就注定了两年前的浏览器必定不能支持.

当然我们还是不能否认,Blazor为如何让更多语言进入前端世界打开了一扇新的大门. 也许未来JavaScript将不仅仅是前端唯一可以使用的利器. 我们会看到C/C++,Python,Java写的前端渲染页面也不一定呢.

当然在后端语言打入前端世界的道路上,WebAssembly也未必是唯一的路劲,比如Scala.js就完全使用了js重写了Scala的库函数,类似的还有Kotlin.js. 可以看到虽然JavaScript已经非常Fancy了,但是后端程序员们进军前端的热情可谓从未停歇过啊.

祝dotnet的应用越来越广,祝广大后端程序员们新年成就慢慢,加薪升职.

部分 FAQ(翻译自Blazor官方)

Q:Is this Silverlight all over again? 这又是一个Silverlight吗? 

No,Blazor is a .NET web framework based on HTML and CSS that runs in the browser using open web standards. It requires no plugin and works on mobile devices and older browsers.

 

当然不是了,Blazor完全是基于Css 和 Html展现的,它的运行不需要任何插件.

 

Q:What features will Blazor support?Blazor都会支持什么功能?

Blazor会支持现在主流单页面Web Application所应具有的功能:

A component model for building composable UI 一个面向组件化UI构建而设计的控件模型 Routing 路由 Layouts 布局 Forms and validation 表单验证 Dependency injection 依赖注入  JavaScript interop 与JavaScript的互操作 Live reloading in the browser during development 开发过程中浏览器的热重载 Server-side rendering 后端渲染(前后端均可渲染页面) Full .NET debugging both in browsers and in the IDE 在浏览器和IDE中都可以获得全面的.Net 调试支持 Rich IntelliSense and tooling 丰富的代码提示和辅助工具 Ability to run on older (non-WebAssembly) browsers via asm.js 在老旧浏览器上能通过 asm.js加载网页 Publishing and app size trimming 进一步缩减发布网站时的大包大小 Q: Can I access the DOM from a Blazor app? 我可以在Blazor中操作DOM吗

You can access the DOM through JavaScript interop from .NET code. However,Blazor is a component based framework that minimizes the need to access the DOM directly.

你可以使用JavaScript互操作层操纵DOM. 但是请注意,Blazor是一个模块化渲染的框架,他的目的就是尽可能减少直接操纵DOM

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3