一. 前言

Blazor 的整体介绍以及特点与优势,建议翻阅 Blazor 介绍。

Blazor 是一个可是使用 .NET/C# 来编写交互式客户端的 Web UI 框架,在官网有一句话概括 “Build client web apps with C#”。在 Blazor 里面有三个比较重要的概念:

  • Components

  • Blazor WebAssembly

  • Blazor Server

Components 翻译过来就是组件,是指 UI 元素,例如页面、对话框或数据输入窗体。Blazor 应用就是由各种各样的组件搭建起来的,类似于 Vue、React、Angular等Js组件。组件的文件名 通常以 .razor 结尾。

Blazor Server 将组件呈现逻辑从 UI 更新的应用方式中分离出来。Blazor Server 在 ASP.NET Core 应用中添加了对在服务器上托管 Razor 组件的支持。可通过 SignalR 连接处理 UI 更新。运行时处理从浏览器向服务器发送 UI 事件,并在运行组件后,将服务器发送的 UI 更新并重新应用到浏览器。Blazor Server 用于与浏览器通信的连接还用于处理 JavaScript 互操作调用。

初尝 Blazor WebAssembly_客户端

Blazor WebAssembly 是一个单页应用(SPA)框架,可用它通过 .NET 生成交互式客户端 Web 应用。Blazor WebAssembly 使用开放的 Web 标准(没有插件或代码转换),适用于移动浏览器等各种新式 Web 浏览器。通过 WebAssembly(缩写为 wasm),可在 Web 浏览器内运行 .NET 代码。WebAssembly 是针对快速下载和最大执行速度优化的压缩字节码格式。WebAssembly 是开放的 Web 标准,支持无插件用于 Web 浏览器。WebAssembly 代码可通过 JavaScript JavaScript 互操作访问浏览器的完整功能。通过浏览器中的 WebAssembly 执行的 .NET 代码在浏览器的 JavaScript 沙盒中运行,沙盒提供的保护可防御在客户端计算机上的恶意操作(这点无法像ActiveX那样了)。

初尝 Blazor WebAssembly_javascript_02

以上内容 摘自官方文档

2019 年 9 月 Blazor 发布了 0.1.0 版本,后面发布了 Blazor Server 正式版,但是 Blazor WebAssembly 一直还在预览版中,Blazor Server 虽然实现了 C# 来编写界面,但是应用UI更新,需要通过UI事件,经过 SignalR 与服务端通信执行业务代码来应用UI更新。最令我感兴趣的是 Blazor WebAssembly,期待已久 ,实现了开放 Web 标准 WebAssembly ,让在客户端浏览器运行C#代码成为现实,我觉得在这一点,微软走在了前列,虽然大家可能会用 Silverlight 的黑历史来吐槽微软,但是这次不一样,WebAssembly 不是微软自家定的。虽然目前它还很年轻,但是我对它还是非常期待与看好。

二. Blazor Server 与 Blazor WebAssembly 对比

1.PWA的支持

Server 不支持,Wasm 支持

2.更新UI流程不同

(1)Blazor Server 在页面加载时,会创建一个 WebSocket 连接(通过 SignalR),会一直发送心跳包来检测连接是否健康。

心跳包:

初尝 Blazor WebAssembly_c#_03

Blazor Server 执行业务代码逻辑是通过 SignalR 发送事件到服务端,服务端执行代码,再返回结果,根据返回的数据渲染UI,应用更新,通过下图可以看到。

初尝 Blazor WebAssembly_c#_04

(2)Blazor WebAssembly 则不同,无需通过服务端来执行C#代码,直接在浏览器执行,来更新UI,获取数据。类似于 Ajax ,通过调用 HTTP Api 来获取数据。

这里需要说明的是,VS里面打断点依然能被正常捕获,是因为 Blazor 框架与 VS 进行了通信来实现 Debug,不然要是不能 Debug 问题可就大了。

初尝 Blazor WebAssembly_服务端_05

在VS中一直F10也会进入到一个JS文件

初尝 Blazor WebAssembly_服务端_06

虽然都能被Debug,但是流程实则完全不一样。

三. 建立第一个 Blazor WebAssembly 应用

1.必备条件

因为 Blazor WebAssembly 是在 2020.05.19 才发布正式版的,所以 Visual Studio 2019 需要更新到新版 >=16.6(macOS >=8.6)

2.创建应用

第一步,选择 Blazor App 模板

初尝 Blazor WebAssembly_javascript_07

第二步,选择 Blazor WebAssembly

初尝 Blazor WebAssembly_javascript_08

建立好的项目具有以下目录结构

初尝 Blazor WebAssembly_c#_09

运行项目,可以看到加载了很多熟悉的 dll

初尝 Blazor WebAssembly_c#_10

其中列表页面,通过 HttpClient 访问了一个静态的 json 文件

初尝 Blazor WebAssembly_c#_11

初尝 Blazor WebAssembly_客户端_12

四. 初体验

1.运行浅析

入口点在 wwwroot/index.html 通过 blazor.webassembly.js 下载 .NET 运行时、应用程序和依赖。这个js文件并不包含在项目文件中,是由 Microsoft.AspNetCore.Components.WebAssembly.Build 工具包提供的,编译生成的时候会输出到目标目录:

初尝 Blazor WebAssembly_客户端_13

2.实现简单逻辑

简单的改了 Counter 的代码,成了一个 Guid 生成器,这点体验还是很好的,直接用C#代码编写逻辑而不是JavaScript,而且是本地运行直接运行C#代码,不需要 Blazor Server 这样的通过 SignalR 通信。

@page "/counter"

    <h1>GUID 生成器</h1>

<div class="row">
    <div class="col-2">
        <input class="form-control" type="text"  value="@_guidValue"/>
    </div>
    <div class="col-10">
        <button class="btn btn-primary" @onclick="GenerateGuid">生 成</button>
    </div>
</div>


@code {
private Guid? _guidValue;

private void GenerateGuid()
{
        _guidValue = Guid.NewGuid();
    }
}

初尝 Blazor WebAssembly_javascript_14

3.与JS的互操作

上面实现了GUID生成器,但是每次生成了都需要自己去输入框复制,不方便,现在实现一个自动复制到剪贴板的功能。

此功能无法百分百通过C#代码来实现,需要与JS进行交互。

先编写 JS:

window.clipboardCopy = {
copyText: function (text) {
        navigator.clipboard.writeText(text).then(function () {
            alert("Copied to clipboard!");
        })
            .catch(function (error) {
                alert(error);
            });
    }
};

该JS放置的位置,可以写在Js文件中,在Index.html中应用,也可以直接写在 Index.html中。

初尝 Blazor WebAssembly_javascript_15

然后在 Razor 组件中注入 JSRuntime,并调用该JS:

@page "/counter"
@inject IJSRuntime JsRuntime

<h1>GUID 生成器</h1>

<div class="row">
<div class="col-2">
<input class="form-control" type="text" value="@_guidValue" />
</div>
<div class="col-10">
<button class="btn btn-primary" @onclick="GenerateGuid">生 成</button>
<button class="btn btn-danger" @onclick="CopyTextToClipboard">复制到剪贴板</button>
</div>
</div>


@code {
    private Guid? _guidValue;

    private void GenerateGuid()
    {
        _guidValue = Guid.NewGuid();
    }

    private async Task CopyTextToClipboard()
    {
        await JsRuntime.InvokeVoidAsync("clipboardCopy.copyText", _guidValue);
    }
}

运行:

初尝 Blazor WebAssembly_服务端_16

小技巧:通过 dotnet watch run 命令可以获得更快乐的开发体验。

五.结束

Blazor WebAssembly 的初次尝试到此就结束了,一直在等正式版,到现在终于等到了,我也是才是学习它,后面陆续会出一些分享文章,希望可以与大家一起学习进步。