通过Blazor使用C#开发SPA单页面应用程序(1)

通过Blazor使用C#开发SPA单页面应用程序(2)

通过Blazor使用C#开发SPA单页面应用程序(3)

前面学习了Blazor的特点、环境搭建及基础知识,现在我们尝试的做个实际的组件。

Ant Design是蚂蚁金服是基于Ant Design设计体系的 UI 组件库,主要用于研发企业级中后台产品。目前官方是基于React和Angular实现的,今年也推出了Vue的实现。其组件涵盖面较广,其组件风格及交互效果还是比较惊艳的,后面准备利用Ant Design的样式文件利用Blazor模仿几个组件的实现。

由于也是新学的Blazor开发,可能实现的方式有些笨拙,希望高手提出宝贵意见,先看看实现的Button 按钮、Grid 栅格、导航栏的效果。

先来看看Button按钮,它支持多种风格,是否只显示图标,loading状态等。实现步骤及主要代码且听我娓娓道来,

首先去antd.css cdn 下载稳定版的css文件,放到 wwwroot 文件夹下。再 _Host.cshtml 引用该文件。

AButtonBase类定义了按钮的属性参数;注册了class名称(例如:class="ant-btn ant-btn-primary")的计算表达式,class内容是根据属性参数的设置情况计算出来的。

属性set 的 ClassMapper.Dirty() 是通知样式名生成方法属性改变了需要重新生成样式名称。

而ClassMapper是用于注册组件需要用到的样式构建类,PrefixCls()是添加样式共用的前缀,Add有多个重载,可以是直接的样式名称;也可以是根据第一个参数的bool表达式来确定,第二个参数的样式是否启用。

using BlazorAntDesign.Core;using Microsoft.AspNetCore.Components;using Microsoft.AspNetCore.Components.RenderTree;using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;

namespace BlazorAntDesign.General{    public class AButtonBase : BaseComponent    {#region Properties/// <summary>/// 设置按钮大小,可选值为 Small、Large 或者不设/// </summary>        [Parameter]protected AButtonSizes ButtonSize        {get => buttonSize;set            {                buttonSize = value;                ClassMapper.Dirty();            }        }private AButtonSizes buttonSize = AButtonSizes.Default;

/// <summary>/// 设置按钮类型,可选值为 Primary、Dashed、Danger 或者不设/// </summary>        [Parameter]protected AButtonTypes ButtonType        {get => buttonType;set            {                buttonType = value;                ClassMapper.Dirty();            }        }private AButtonTypes buttonType = AButtonTypes.Default;

/// <summary>/// 设置按钮形状,可选值为 Circle、 Round 或者不设/// </summary>        [Parameter]protected AButtonShapes ButtonShape        {get => buttonShape;set            {                buttonShape = value;                ClassMapper.Dirty();            }        }private AButtonShapes buttonShape = AButtonShapes.Default;

/// <summary>/// 设置 button 原生的 type 值,可选值请参考 HTML 标准/// </summary>        [Parameter]protected AButtonHTMLTypes HtmlType { get; set; } = AButtonHTMLTypes.Button;

/// <summary>/// 按钮标题/// </summary>        [Parameter]protected string Title        {get => title;set            {                title = value;                ClassMapper.Dirty();            }        }private string title;

/// <summary>/// 设置按钮的图标名称/// </summary>        [Parameter]protected string IconName { get; set; }

/// <summary>/// 将按钮宽度调整为其父宽度的选项/// </summary>        [Parameter]protected bool Block        {get => block;set            {                block = value;                ClassMapper.Dirty();            }        }private bool block;

/// <summary>/// 幽灵属性,使按钮背景透明。幽灵按钮将按钮的内容反色,背景变为透明,常用在有色背景上。/// </summary>        [Parameter]protected bool Ghost        {get => ghost;set            {                ghost = value;                ClassMapper.Dirty();            }        }private bool ghost;

/// <summary>/// 设置按钮载入状态/// </summary>        [Parameter]protected bool Loading        {get => loading;set            {                loading = value;                ClassMapper.Dirty();            }        }private bool loading;

/// <summary>/// 按钮失效状态/// </summary>        [Parameter]protected bool Disabled { get; set; }

        [Parameter]protected RenderFragment ChildContent { get; set; }

/// <summary>/// 点击按钮时的回调/// </summary>        [Parameter]public EventCallback<UIMouseEventArgs> OnClick { get; set; }//protected System.Action Clicked { get; set; }

protected bool click_animating { get; set; }#endregion

protected override void RegisterClasses()        {            ClassMapper.PrefixCls("ant-btn")                    .Add(() => ClassMapper.GetEnumName(buttonSize))                    .Add(() => ClassMapper.GetEnumName(buttonType))                    .Add(() => ClassMapper.GetEnumName(buttonShape))                    .Add(() => Block, () => "block")                    .Add(() => Ghost, () => "background-ghost")                    .Add(() => Loading, () => "loading")                    .Add(() => string.IsNullOrEmpty(title) && ChildContent == null, () => "icon-only");

base.RegisterClasses();        }

protected void buttonDown()        {            click_animating = false;        }

protected void buttonUp()        {            click_animating = true;        }

    }}

AButtonSizes、AButtonTypes、AButtonShapes、AButtonHTMLTypes 属性参数是定义的枚举,例如:

namespace BlazorAntDesign.General{/// <summary>/// 按钮尺寸选项/// </summary>public enum AButtonSizes    {/// <summary>/// 缺省,中/// </summary>        [ClassNamePart("")]        Default,

/// <summary>/// 大/// </summary>        [ClassNamePart("lg")]        Large,

/// <summary>/// 小/// </summary>        [ClassNamePart("sm")]        Small    }}
namespace BlazorAntDesign.General{/// <summary>/// 按钮类型选项/// </summary>public enum AButtonTypes    {/// <summary>/// 缺省,次按钮/// </summary>        [ClassNamePart("")]        Default,

/// <summary>/// 主按钮/// </summary>        Primary,

/// <summary>/// /// </summary>        Ghost,

/// <summary>/// 虚线按钮/// </summary>        Dashed,        Danger    }}

AButtonBase类继承自自定义的BaseComponent,BaseComponent继承自Blazor的ComponentBase类。

BaseComponent主要定义了所有组件共用的属性,ElementId、Style、ClassMapper等,

using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.AspNetCore.Components;

namespace BlazorAntDesign.Core{public abstract class BaseComponent : ComponentBase, IDisposable    {#region Members

private bool disposed;

private ElementRef elementRef;

#endregion

#region Constructors

public BaseComponent()        {            ElementId = Utils.IDGenerator.Instance.Generate;

            ClassMapper = new ClassMapper();            RegisterClasses();        }

#endregion

#region Methodsprotected virtual void RegisterClasses()        {            ClassMapper.AddCustomClass(() => customClass);        }

public void Dispose()        {            Dispose(true);            GC.SuppressFinalize(this);        }

protected virtual void Dispose(bool disposing)        {if (!disposed)            {if (disposing)                {if (ClassMapper != null)                    {//ClassMapper.Dispose();                        ClassMapper = null;                    }                }

                disposed = true;            }        }

#endregion

#region Properties

/// <summary>/// 定义用户自定义的 ClassName/// </summary>        [Parameter]protected string ClassName        {get => customClass;set            {                customClass = value;                ClassMapper.Dirty();            }        }private string customClass;

/// <summary>/// Gets the reference to the rendered element./// </summary>public ElementRef ElementRef { get => elementRef; protected set => elementRef = value; }

/// <summary>/// 获取 element 唯一 Id./// </summary>public string ElementId { get; }

        [Parameter]protected string Style { get; set; }

/// <summary>/// 获取 ClassMapper./// </summary>protected ClassMapper ClassMapper { get; private set; }

#endregion    }}
@inherits BlazorAntDesign.General.AButtonBase

<button class="@ClassMapper.Class"        type="@(Enum.GetName(typeof(AButtonHTMLTypes), HtmlType).ToLower())"        ant-click-animating-without-extra-node="@(click_animating ? "true" : "")"        disabled="@Disabled"        @onkeydown="@buttonDown"        @onmousedown="@buttonDown"        @onkeyup="@buttonUp"        @onmouseup="@buttonUp"        @onclick="@OnClick">    @*图标*@    @if (Loading)    {<AIcon IconName="loading"></AIcon>}    else    {        if (!string.IsNullOrEmpty(IconName))        {<AIcon IconName="@IconName"></AIcon>}    }    @*标题*@    @if (!string.IsNullOrEmpty(Title))    {<span>@Title</span>}@*子内容*@    @ChildContent</button>

其中  @inherits BlazorAntDesign.General.AButtonBase 是代码隐藏方式,指定后台代码继承自AButtonBase类,button class="@ClassMapper.Class",将采用的样式根据指定的属性值计算出来赋值给button的class属性。下面根据属性设置判断是否显示图标、标题、子内容。

建立DemoButton.razor文件,样例代码如下:

@page "/DemoButton"@using BlazorAntDesign.General;

<div style="border:1px solid beige;padding:10px"><AButton Title="Default"></AButton><AButton Title="Primary" ButtonType="AButtonTypes.Primary"></AButton><AButton Title="Danger" ButtonType="AButtonTypes.Danger"></AButton><AButton Title="Dashed" ButtonType="AButtonTypes.Dashed"></AButton><AButton Title="Disabled" Disabled="true"></AButton><AButton ButtonType="AButtonTypes.Primary" IconName="download" ButtonShape="AButtonShapes.Circle"></AButton><AButton Title="下载" ButtonType="AButtonTypes.Primary" IconName="download" ButtonShape="AButtonShapes.Round"></AButton><AButton Title="下载" ButtonType="AButtonTypes.Primary" IconName="download"></AButton><AButtonGroup><AButton ButtonType="AButtonTypes.Primary" IconName="left">Backward</AButton><AButton ButtonType="AButtonTypes.Primary">Forward<AIcon IconName="right" /></AButton></AButtonGroup><AButton Title="Loading" ButtonType="AButtonTypes.Primary" Loading="true"></AButton><AButton Title="Click me!" ButtonType="AButtonTypes.Primary" Loading="@isLoading" OnClick="@(()=> { isLoading = true; })"></AButton></div><div style="border:1px solid beige;padding:10px;margin-top:5px"><AButton IconName="search" ButtonType="AButtonTypes.Primary" ButtonShape="AButtonShapes.Circle"></AButton><AButton IconName="search" ButtonType="AButtonTypes.Primary">按钮</AButton><AButton IconName="search" ButtonShape="AButtonShapes.Circle"></AButton><AButton IconName="search">按钮</AButton><AButton IconName="search" ButtonType="AButtonTypes.Dashed" ButtonShape="AButtonShapes.Circle"></AButton><AButton IconName="search" ButtonType="AButtonTypes.Primary">按钮</AButton></div>

@code{    private bool isLoading = false;

    private void LoadingClick()    {        isLoading = true;    }}

@page "/DemoButton"   为组件路由

@using BlazorAntDesign.General;       为应用组件命名空间

好了Button的实现思路今天就学习到这了,希望有兴趣的同仁共同学习探讨,让Blazor真正走向SPA开发的舞台,让.net core七龙珠面向全栈开发,更好的拥抱社区,刷新业界对.net体系的认知。

Blazor 在发展:

微软已将 Blazor 移出了实验阶段,进入了官方预览版。使用组件模型进行服务器端渲染的 Blazor 版本将与.NET Core 3 的最终版本一起发布(请参阅.NET Core 路线图),客户端版本将在随后不久发布。还有工作要完成:调试体验极其有限,必须改进;有机会通过提前编译生成本机 Wasm 来优化代码性能;在将未使用的代码库发送到浏览器之前,需要从库中删除未使用的代码,从而降低总体大小(这个过程称为树抖动)。对 WebAsssembly 的兴趣和采用与日俱增,借助 Blazor,编写可以在任何地方运行的 C#和.NET 代码的梦想终于实现了。

原文链接:https://www.cnblogs.com/liuxtj/p/11377680.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

通过Blazor使用C#开发SPA单页面应用程序(4) - Ant Design相关推荐

  1. 通过Blazor使用C#开发SPA单页面应用程序(1)

    2019年9月23--25日 .NET Core 3.0即将在.NET Conf上发布! .NET Core的发布及成熟重燃了.net程序员的热情和希望,一些.net大咖也在积极的为推动.NET Co ...

  2. 通过Blazor使用C#开发SPA单页面应用程序(2)

    今天我们尝试创建一个默认的Blazor应用. .Net Core 3.0需要Visual Studio 2019 的支持. 安装.Net Core 3.0 预览版 SDK版本,注意预览版对应的VS版本 ...

  3. 从零开始学习小程序1-1开发一个单页面小程序

    1,在本地电脑中创建一个文件夹"test",2,打开微信开发者工具 3,新建项目文件test,按以下步骤填写完整4,初始页面是这样的5,点开app.json页面,删掉原始代码,配置 ...

  4. 单页面应用程序的优缺点

    一,优点 SPA 单页面应用程序最显著的 3 个优点如下: ① 良好的交互体验 单页应用的内容的改变不需要重新加载整个页面,只有一个HTML页面 因为没有页面之间的跳转,不会出现"白屏现象& ...

  5. Java快速开发平台,JEECG 3.7.5 Vue SPA单页面应用版本发布

    JEECG 3.7.5 Vue SPA单页面应用版本发布 导读            ⊙ Vue+ElementUI SPA单页面应用 ⊙Datagrid标签快速切换BootstrapTable列表风 ...

  6. spa单页面应用html缓存问题

    一.背景 浏览器的http请求都有一个缓存机制,简单点说就是同路径同名文件会默认被缓存下来,提升下次访问时的速度,默认只有刷新页面或长时间未访问时才会刷新缓存. 而spa单页面应用是通过路由切换来访问 ...

  7. 当spa单页面应用遇上SEO,蛋痛的经历

    spa单页面应用优点当然毋庸置疑:效果酷炫,我在视觉和产品面前无从反驳:性能高速度快,全JS嘛当然快,我在运维和产品面前无言以对:运算分散,异步加载,又省硬件又省流量,我在开发和产品面前彻底投降:JS ...

  8. [vue] SPA单页面的实现方式有哪些?

    [vue] SPA单页面的实现方式有哪些? 1.监听地址栏中hash变化驱动界面变化2.用pushsate记录浏览器的历史,驱动界面发送变化3.直接在界面用普通事件驱动界面变化它们都是遵循同一种原则: ...

  9. [vue] 说说你对SPA单页面的理解,它的优缺点分别是什么?

    [vue] 说说你对SPA单页面的理解,它的优缺点分别是什么? 介绍:SPA应用就是一个web应用,可理解为:是一种只需要将单个页面加载到服务器之中的web应用程序.当浏览器向服务器发出第一个请求时, ...

最新文章

  1. java二叉树镜像_给定一个二叉树,检查它是否是镜像对称的。
  2. 用MacBook对交换机进行初始化配置
  3. Python中使用元组对ndarray矩阵的某个维度进行选取和调序的操作
  4. :new与:old的用法
  5. 在html页面提交值到动态页面时出现中文值为乱码的解决方案
  6. php语言难点,PHP知识难点TOP3,挑战一下你
  7. mysql+tushare搭建本地数据库
  8. Echarts双纵轴分隔线合并解决方案
  9. 远程连接Ubuntu服务器
  10. eclipse中怎么安装spring插件_安装eclipse中容易遇到的问题
  11. 嵌入式语音识别系统之电路设计原理
  12. 分享我的Linux开发环境
  13. 一个简单的前后端分离案例
  14. 解决gitlab内存占用过多的问题
  15. C++11的std::declval与decltype
  16. 设计模式学习笔记-装饰模式
  17. 公众号网课搜题API系统对接教程
  18. 论文总结与展望怎么写?
  19. 学计算机的可以考哪种证书,自学比较容易考的证书 哪些证书有用
  20. Centos 7 安装 jq json 插件以及使用方法

热门文章

  1. 小小一招解决“INSERT EXEC 语句不能嵌套”的问题
  2. 轻松掌握使用 SQL Server 浏览器,解决SQL Server 2005跨网段不能连接问题
  3. 从别的地方转来的 网址
  4. gcc oracle mysql_Linux下C语言访问Oracle数据库Demo
  5. VSCode的Teams插件
  6. 算法笔记_226:填符号凑算式(Java)
  7. 加速你的Hibernate引擎(上)
  8. 给定两个二叉树T和S,判断S是否为T的子树
  9. IPV6迎来商业元年 运营商短期盈利模式成难点
  10. HDU 2896 病毒侵袭【AC自动机】