Blazor WASM 实现人民币大写转换器

点击上方蓝字关注“汪宇杰博客”

导语

.NET 5 正式发布已经有一段时间了,其中 Blazor 技术是该版本的亮点之一。作为微软技术的被坑者,年少的我曾经以为 SilverLight 能血虐 Flash,Zune 能团灭 iPod,WP 能吊打 iPhone,UWP 能统一全平台…… 可是后…… 最终步入大龄程序员的我发现,只有陪伴了我将近 20 年的ASP.NET 还没有完蛋。于是我这两天花了点时间,尝试将我的一个 UWP 小工具用 Blazor 重写,分享给大家。

无法抢救的 UWP

人民币大写转换器” 是我年少无知时开发的小工具之一,它的主要功能有:

- 将数字金额转化为大写中文

- 复制结果

- 使用中文语音朗读结果

- 显示参照表

可惜 UWP 不论是充满 Bug 的 SDK,Runtime,还是微软的龟速更新与混乱的规划,都已经无可救药了,是时候给应用找个新家了。

Blazor

Blazor 是 .NET Core 时代微软推出的用于 Web 应用开发的新框架,它可以运行在服务器端,也可使用 WASM 运行在客户端,即浏览器中。

对我来说,这个技术最吸引人的,就是 WASM。像我这种已经30多岁,学不了新东西的 .NET 程序员,根本搞不定 Angular、Vue、React 这些花里胡哨的框架,而 Blazor WASM 是把 .NET 运行时搬到了浏览器端,和 SilverLight 类似,但这次是以WASM标准的形式运行,不需要安装插件,并且也能跨平台。

于是我可以继续使用熟悉的 .NET 和 C# 开发 SPA Web 应用。更重要的是,既然是原汁原味的 .NET,就可以很方便的重用以前的代码,以及现成的成千上万个 NuGet 包,而不用像一个新发明的框架那样从0开始积累生态。

我 996 了 2 小时,成功将“人民币大写转换器”重写到 Blazor WASM,效果如下:

Demo:https://rmbcap.azurewebsites.net/
源代码:https://github.com/EdiWang/RMBCapitalization-Blazor

由于篇幅关系,本文不叙述重写的每处细节,只参数关键点。其他细节大家可到 GitHub 阅读源代码了解。

创建 Blazor WASM 工程

我们可以使用 Visual Studio 2019 创建 Blazor WASM 工程。

选择 Blazor WebAssembly App 就可以了

工程结构

一个 Blazor WASM 项目的典型结构如上图。Program.cs 包含应用如何启动与承载的逻辑。

wwwroot 中的文件为纯 HTML/CSS/JS 文件,不包含.NET的逻辑。其中 index.html 为承载应用的默认页面,和 Angular 等 SPA 框架非常类似,它将会把应用页面加载到 <div id="app"> 中。

MainLayout.razor 是整个应用的布局页面,如果你有多个页面和视图,那么通常这里会放 Header,Footer 等内容。

Index.razor 为应用的默认主页。我这个应用只有一个页面,所以一切逻辑都在这里实现就可以了。

可重用的代码

人民币大写的转换类与框架和平台无关,因此完全可以直接复制到Blazor工程里用,即 RMBConverter.cs。

UWP 应用的视图通常采用 MVVM 模式开发,这些逻辑可以很方便的迁移到 Blazor。

Index.razor

就像写 MVC 的 cshtml 一样,使用熟悉的 Razor 语法,就能绑定数据和事件。

对于 input,简单的双向数据绑定可以直接用 @bind="属性" 实现。但我这个应用里要求用户一边输入金额一边进行实时计算,所以只能写成事件绑定。

<div>

    <h3> @Result </h3>

</div>

<div>

    <div>

        <input type="text" @bind-value="InputAmount" @bind-value:event="oninput" />

    </div>

    <div>

        <button @οnclick="CopyResult">复制</button>

        <button @οnclick="ReadAloud">朗读</button>

        <button @οnclick="Clear">清除</button>

    </div>

</div>

对于有参数的事件处理函数,要注意它和正常 C# 写事件一样,是个 Lambda 表达式,如果放在循环里的话要注意变量的值是在循环里被修改。

下面的代码必须使用 var num = i 来存储 i 的值,如果直接使用 KeyPadClicked(i),那么 i 一定永远等于1。

<div class="row">

    @for (int i = 1; i <= 9; i++)

    {

var num = i;

        <div class="col-4">

   <button class="btn btn-light key" @οnclick="() => KeyPadClicked(num.ToString())">@i</button>

        </div>

    }

</div>

<div class="row">

    <div class="col-8">

 <button class="btn btn-light key" @οnclick='() => KeyPadClicked("0")'>0</button>

    </div>

    <div class="col">

 <button class="btn btn-light key" @οnclick='() => KeyPadClicked(".")'>.</button>

    </div>

</div>

和 XAML 的 MVVM 以及 Angular 稍有不同的是,处理逻辑不是在 code behind 文件里写的,而是在 razor 页面本身写。如果能写成 Index.razor.cs 就干净了。

@code {

    private string _inputAmount;

    public string InputAmount

    {

        get => _inputAmount;

        set

        {

            _inputAmount = value;

            // 验证和处理逻辑...

            Result = string.IsNullOrWhiteSpace(_inputAmount) ?

                    string.Empty :

                    RMBConverter.GetCapitalizedRmb(InputAmount);

        }

    }

    public string Result { get; set; }

    private async Task CopyResult()

    {

        // ...

    }

    private async Task ReadAloud()

    {

        // ...

    }

    private void Clear()

    {

        InputAmount = string.Empty;

    }

    private void KeyPadClicked(string value)

    {

        InputAmount += value switch

        {

            "0" when InputAmount != "0" => 0,

            "." when !InputAmount.Contains(".") => ".",

            _ => value

        };

    }

}

需要重新实现的功能

复制文字

在 UWP 中,复制可以调用 Windows 的 Clipboard API 来完成。但是在浏览器端,没有 Windows 的 API,Blazor 也没有封装剪切板 API,因此我们只能借用 JS 来完成。

index.html

window.clipboardCopy = {

    copyText: function (text) {

        navigator.clipboard.writeText(text).then(function () {

            console.log(text);

        })

            .catch(function (error) {

                alert(error);

            });

    }

};

Index.razor

使用依赖注入,引入 IJSRuntime 的实例。这是 Blazor 用于和 JavaScript 交互的接口。

@inject IJSRuntime JavaScriptRuntime

然后就可以调用 JS 进行复制

private async Task CopyResult()

{

    if (!string.IsNullOrWhiteSpace(Result))

    {

        await JavaScriptRuntime.InvokeVoidAsync("clipboardCopy.copyText", Result);

    }

}

朗读

类似的,在 UWP 里,朗读使用的是 Windows 的 SpeechSynthesizer API。浏览器端也有个类似的 SpeechSynthesisUtterance。

index.html

window.readAloud = {

    readText: function (text) {

        let utterance = new SpeechSynthesisUtterance(text);

        utterance.lang = 'zh-CN';

        speechSynthesis.speak(utterance);

    }

}

Index.razor

private async Task ReadAloud()

{

    if (!string.IsNullOrWhiteSpace(Result))

    {

        await JavaScriptRuntime.InvokeVoidAsync("readAloud.readText", Result);

    }

}

本地应用

目前 Blazor WASM 还没有本地应用的官方支持,必须打开浏览器才能使用,现有的版本只能使用PWA完成一部分本地应用化操作。但在今年即将发布的 .NET 6 版本中,Blazor 会迎来官方最纯正的本地应用支持。只要不出自 SilverLight、Zune、WP、WinRT、UWP 团队之手,就不会被坑!

现存的问题

Blazor WASM 虽然看着香,但目前有一些痛点还有待解决。

首先,框架本身的体积依然较大,由于众所周知而不可描述的原因,如果服务器部署在海外,那么我国网络加载 Blazor 应用会比较慢。

另外,不是所有版本的浏览器都可以跑 WASM,尤其是手机端。Blazor 的兼容性相比 Angular,Vue,React 等,还有些差距。

总结

使用 Blazor WASM 开发 Web 应用能够让 .NET 程序员充分利用既有的知识和技能快速上手,结合 Web 的强大生态 与 .NET 的高效生产力,成就不凡。而 UWP 只能哭晕在厕所也没人听见……

汪宇杰博客

Azure | .NET | 微软 MVP

无广告,不卖课,做纯粹的技术公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vs2010中svn使用教程_VS2010中使用ankhSVN

给大家介绍一些SVN的入门知识&#xff01;希望对大家的学习起到作用&#xff01;关于SVN与CVS的相关知识&#xff0c;大家可以自己去google一下。一、准备SVN是一个开源的版本控制系统&#xff0c;它可以记录所有的文件修改版本。CVS也是一个版本控制系统&#xff0c;可是现在大…

金山安全实验室公布中国互联网六大类钓鱼网站

金山安全实验室公布中国互联网六大类钓鱼网站金山安全实验室研究人员对中国大陆钓鱼网站的普遍特征进行分析&#xff0c;发现以下六个领域最容易被钓鱼网站***&#xff1a;1.QQ十年庆典、QQ抽奖、腾讯活动&#xff1b;2.证券、股票分析、黑庄、理财专家等财经领域&#xff1b;3…

c语言用递归法判断回文字符串,递归方式判断一个字符串是否为回文字符串

/** 递归方式判断一个字符串是否为回文字符串*/public class PartitionTest{public static void main(String[] args) {String str "123456654321";System.out.println("srcString "str);System.out.println("srcString is "(isPartition(str)…

npm 安装less插件_IDEA编译less插件LESS CSS Compiler的安装

2.安装Node.js,下载3.打开idea→settings→plugins 安装&#xff1a;“nodejs”插件&#xff0c;并按以下步骤进行配置&#xff1a;4.打开idea→settings→Languages & Frameworks→Node.js and NPM&#xff1b;在打开的面板中点击右侧“”加号按钮添加需要的“less”组件(…

程序员过关斩将--领导说我的类的职责不单一

“为什么类的职责要单一化&#xff1f;“类的职责单一化很容易吗&#xff1f;首先&#xff0c;我要提醒一下看到这篇文章的同学&#xff0c;我认为保证类&#xff08;一定是类吗&#xff1f;&#xff09;的单一职责并不容易软件开发过程中&#xff0c;自古就流传着几大规则&…

从概念到案例,机器学习应该掌握的20个知识点

随着科技的发展&#xff0c;计算机对人类的生产活动和社会活动产生了极为重要的影响&#xff0c;同时以强大的生命力飞速发展着。目前计算机正广泛用于社会各个领域&#xff0c;并朝着微型化、网络化、智能化和巨型化的方向前进。说到智能化&#xff0c;大家最先想到的应该就是…

闲来没事写个记事本玩玩!!!

这两天工作压力大&#xff0c;还好今天见着太阳了&#xff0c;这会儿没事写了个记事本&#xff0c;功能单一&#xff0c;适合练手&#xff0c;可能对新手会有所帮助&#xff0c;贴上来看看吧&#xff0c; 说到实现 记事本&#xff0c;我们应该选择什么样的控件呢&#xff0c;Te…

在c语言程序中将数据分为两种,2012年计算机二级C语言考点归纳汇总(一至四章)...

第1章程序设计基本概念考点归纳1.1 C语言的特点C语言是近年来非常流行的语言&#xff0c;很多人宁愿放弃已经熟悉的其他语言而改用C语言&#xff0c;其原因是C语言有优于其他语言的一系列特点。下面是C语言的主要特点&#xff1a;(1)语言简洁、紧凑&#xff0c;并且使用方便、灵…

LG将授权webOS给其他电视厂商使用

喜欢就关注我们吧&#xff01;LG 将向其他公司提供 webOS。根据 LG 发布的公告&#xff0c;其自家电视机搭载的专有系统 webOS 将会授权给其他的外部电视厂商使用。被授权使用 webOS 的电视厂商还会获得来自 LG 的 Magic Motion 遥控器&#xff0c;此外&#xff0c;系统的语音控…

数据之美,堪比好莱坞大片!

看完下面的几张图&#xff0c;你就知道自己有多无知了。堪称是好莱坞大片啊&#xff01;1城市3D空间通过2D瓦片图层的3D化&#xff0c;能够在经度维度、量级、时间多个维度上真实还原城市3D空间。例子中为模拟的轨迹数据和旧金山食物供应商分布。2GPS轨迹分布以三种不同的方式描…

redis 公网ip访问_Redis很重要,怎么只允许指定IP访问?

在 Linux 中安装了redis 服务&#xff0c;当在客户端通过远程连接的方式连接时&#xff0c;报could not connect错误。错误的原因很简单&#xff0c;就是没有连接上redis服务&#xff0c;由于redis采用的安全策略&#xff0c;默认会只准许本地访问。需要通过简单配置&#xff0…

HSRP的配置问题

HSRP的配置问题<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />实验目的&#xff1a;理解和掌握路由热备份的配置步骤和原理实现网关的冗余功能实验环境&#xff1a;如下图所示<?xml:namespace prefix v ns "urn:sch…

Dotnet的垃圾回收

最近在做一个项目&#xff0c;用到了大量的非托管技术&#xff0c;所以垃圾回收变得很重要。在说垃圾回收之前&#xff0c;先说说两个概念&#xff1a;托管代码&#xff0c;是由CLR管理的代码非托管代码&#xff0c;是由操作系统直接执行的代码在早期C的时候&#xff0c;内存分…

c语言抬起按键,c语言获得键盘的按键

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼TC 2.0版#include#includeint main(){int key;while(1){keygetch();/*用于去掉第一个字节*/if(key27) break; /*如果是ESC退出*/if(key>31 && key<127) /*如果不是特殊键*/{printf("You have pressed %c Press …

数学从小学开始“梯次掉队”?别让课本的枯燥“浇灭”孩子对数学的兴趣

1、2、3、4、5……从孩子用手指数数开始&#xff0c;就与数学结下了不解之缘。进入幼儿园&#xff0c;在老师的指导下画出三角形&#xff0c;圆形等&#xff0c;这是数学中的几何。稍大一点&#xff0c;到商店里买东西&#xff0c;开始懂得买的东西是多还是少&#xff0c;是大还…

行者运行脚本命令_行者脚本指令说明

例2:SellItem(返回卷轴[ID736],2;复活卷轴[ID737],3)例3:SellItem(*)卖出道具设定中设为"卖"的全部物品SaveItem(名字[IDx],数量)例1:SavelItem(返回卷轴[ID736],2)例2:SavelItem(返回卷轴[ID736],2;复活卷轴[ID737],3)例3:SavelItem(*)保存道具设定中设为"存&q…

史上最全最常用批处理260多个打包下载

请看这里转载于:https://blog.51cto.com/sunxuewei/281145

中南民族大学c语言报告,中南民族大学信C语言实验报告.doc

中南民族大学信C语言实验报告中南民族大学管理学院学生实验报告课程名称&#xff1a; C语言程序设计姓  名&#xff1a;微博song-style是坏学长学  号&#xff1a;年  级&#xff1a;  2011专  业&#xff1a;信息管理与信息系统指导教师&#xff1a;实验地点&#xff1…

用算法撩妹都不会,别跟我说你是程序员

程序员浪漫的表白方式可以说是花样百出&#xff0c;为什么用在自己身上就没效果呢&#xff1f;作为一个程序员“身边的女生”&#xff0c;小编觉得&#xff0c;大部分程序员没有女朋友&#xff0c;很可能是恋爱技能bug太多&#xff0c;当你还不确定那个女生对你的喜欢程度&…

CSRobot gen:mssql-c#类型映射

CSRobot的gen命令&#xff0c;有一个参数--map&#xff0c;是指数据库字段类型到实体类型映射&#xff0c;本例是sql server到csharp的类型映射&#xff1a;SQL ServerC#bigintInt64binaryByte[]bitBooleancharString&#xff0c;Char[]date DateTimedatetimeDateTimedatetime2…