Util应用框架快速入门(3) - UI 开发入门
本文是Util应用框架 Angular UI 开发快速入门教程.
Util前端技术概述
Util 应用框架目前仅支持用于开发管理后台的 UI.
本文介绍了 Util UI 的技术特点和功能支持.
UI 技术选型
-
Js语言
-
TypeScript
TypeScript 是 微软开发的脚本语言, 扩展了弱类型的 Javascript,提供增强的语法和强类型支持.
为编辑器代码提示和语法错误检测奠定坚实基础.
-
-
Js框架
-
Angular 组件库
-
Angular 微前端框架
-
Angular Module Federation
如果你的项目包含大量 Angular 模块,所有文件在同一个项目中,会导致开发环境卡顿和缓慢.
发布项目也可能需要很长时间.
另外,如果某个模块需要进行修改,哪怕只修改一行代码,也需要对所有模块重新发布.
与后端的微服务类似,微前端是前端的项目拆分方法.
微前端将不同的 Angular 模块拆分到不同项目中,可以独立开发,独立测试和独立部署.
无论你是否使用微服务架构,均可使用微前端拆分方式.
Angular Module Federation 是基于Webpack模块联合的Angular微前端解决方案.
-
Util Angular UI 特点
-
使用 Visual Studio 开发工具
前端开发一般使用 Visual Studio Code , 不过 Util Angular UI主要使用 Razor 页面,使用 Visual Studio 更方便.
-
组件扩展支持
除了支持 Ng Zorro 原生功能外,Util UI还对常用组件进行了扩展.
最重要的扩展是支持常用组件直接发出 Api 请求,而不用定义额外的服务.
-
Razor TagHelper 支持
Util Angular UI不仅可以使用 html 页面,还能使用 .Net Razor 页面.
Razor 页面可以使用 TagHelper 服务端标签.
Util 已将大部分 Ng Zorro 组件封装为 TagHelper 标签.
除了获得强类型提示外,TagHelper 作为抽象层,提供更简洁的标签语法.
另一个强大之处在于Lambda表达式支持, 可以将DTO直接绑定到 TagHelper 标签上.
能够从Lambda表达式提取元数据,并自动设置大量常用属性,比如name,验证,模型绑定等.
-
前后分离
一些开发人员看到 Util Angular UI 使用 .Net Razor 页面,可能认为 UI 与 .Net 高度耦合,但现在的趋势是前后分离.
所谓前后分离,是前端UI和后端API没有依赖,更换某一端对另一端没有影响.
另外,前后分离后,前端UI和后端API可以由不同的开发人员完成.
.Net Razor页面仅在开发阶段提供帮助,在发布时, Razor 页面会转换为 html ,后续发布流程与纯前端开发方式相同.
一旦发布成功,将完全脱离.Net 环境,可以使用 Nginx 容器承载它.
发布后的产物,与你使用纯前端方式开发打包没有区别.
如果你喜欢,可以把后端API换成JAVA,也能正常运行.
-
配套Api支持
前端UI和后端API的开发是两个完全不同的领域.
但开发一个功能,又需要前端和后端的配合,他们需要沟通,作出一些约定.
对于配合不到位的团队,前后端的沟通成本可能很高,另外提供的API可能无法满足UI的需求,从而让前端代码变得畸形.
通常.Net开发人员的Js编程功底高于常规前端人员,前端人员更擅长样式布局.
Util Angular UI 不仅提供对前端组件的封装,同时也为常见功能提供 Api 支持.
对于使用 Util Angular UI 的团队, 将 UI 和 API 交给同一个.Net开发人员就是最好的选择.
前端人员仅调整界面样式即可.
不仅减少了沟通成本, API和前端组件的高度集成封装,让常规功能的开发效率得到大幅提升.
当然,这对 .Net 开发人员的水平有一定要求.
-
本地化支持
得益于 Ng Alain 本地化的良好设计, 可以使用 i18n 管道进行文本的本地化转换.
'文本' | i18n
不过对于需要支持本地化的项目,这依然是一个负担,每个表单项,每个表格项,每个文本,可能都需要添加 i18n 管道.
Util Angular UI 让本地化开发更进一步,对大部分组件提供了本地化支持,只有极少数文本需要手工添加 i18n 管道.
-
授权访问支持
Ng Alain提供了授权访问的支持.
Util Platform权限模块基于资源和角色的设计,可以很好的与 Ng Alain授权进行集成.
你可以控制菜单和任意区域根据权限显示和隐藏.
-
微前端支持
Util Angular UI 引入了 Angular Module Federation , 能够将 Angular 模块拆分到不同项目中,可以独立开发,独立测试和独立部署.
对于大中型项目,这是非常有必要的.
Util Angular UI 功能列表
Util Angular UI 主要由 util-angular 和 Util.Ui.NgZorro 两个库提供支持.
-
util-angular 功能列表
util-angular 是一个 Js 库, 由Curd组件基类, Ng Zorro常用组件扩展指令和一组工具类组成.
-
基础类型
- ViewModel - 视图模型基类
- TreeViewModel - 树形视图模型基类
- TreeNode - 树形节点基类
- PageList - 分页列表
- QueryParameter - 查询参数基类
- TreeQueryParameter - 树形查询参数基类
- Result - 服务端返回结果
- StateCode - 服务端状态码约定
- SelectItem - 列表项
- SelectList - 列表
- SelectOptionGroup - 列表配置组
- SelectOption - 列表配置项
-
工具类
- 浏览器本地存储操作
- Cookie操作
- 事件总线操作
- 本地化操作
- Ioc操作
- 加载操作
- 路由操作
- 弹出层操作
- 抽屉操作
- 表单操作
- Http操作
- Web Api操作
- 消息操作
- ...
-
Crud组件基类
- 编辑组件基类
- 表格编辑组件基类
- 树形编辑组件基类
- 查询组件基类
- 表格查询组件基类
- 树形表格查询组件基类
-
Ng Zorro指令扩展
- 必填项验证扩展指令
- 验证消息扩展指令
- Ng Zorro 按钮扩展指令
- Ng Zorro 选择框扩展指令
- Ng Zorro 表格扩展指令
- Ng Zorro 表格编辑扩展指令
- Ng Zorro 树形表格扩展指令
- Ng Zorro 树形扩展指令
- Ng Zorro 上传扩展指令
-
-
Util.Ui.NgZorro 库介绍
Util.Ui.NgZorro 是一个 C# 类库,包含 TagHelper标签和树形控制器等类型.
绝大部分 Ng Zorro 组件已经封装.
由于组件很多,就不一一列出.
Util Angular UI 已知缺陷
Util Angular UI 在提供大量支持的同时,也存在一些缺陷.
-
开发阶段运行比较缓慢
与 Visual Studio Code 相比,使用 Visual Studio 开发 Angular 项目要慢一些,如果使用了 Resharper 插件,则会更慢.
除开发工具影响外, Util Angular UI 在开发阶段需要启用 Angular JIT( 即时编译 ), 运行会变慢.
另外, Util Angular UI 在开发阶段需要访问 Razor 页面,每当项目启动,Angular 主模块加载的所有组件都会发出 Razor 页面请求.
不过运行缓慢仅存在于开发阶段,一旦发布,则与纯前端开发方式的运行速度相同.
-
无法使用 Angular 常规延迟加载方式
你不能使用 loadChildren 延迟加载模块,这是因为开发阶段组件的 templateUrl 指向 Razor 页面地址, 必须使用 Angular JIT 模式,等待运行时再获取组件模板.
这个问题从 Angular 13 开始出现, Angular 13弃用了传统的视图引擎, 使用 loadChildren 加载指向 Razor 页面地址的组件会报异常.
解决它的方法是使用微前端方案延迟加载模块, 当然你也可以回退到 Angular 13之前的版本.
在同一个 Util Angular UI 项目中,你必须把所有的子模块加载到主模块中,并配置微前端将子模块发布为可独立加载包.
Util Angular UI 适合你吗?
Util Angular UI 是为 .Net 全栈工程师准备的,如果你更喜欢使用 Visual Studio 开发,喜欢代码提示,喜欢更简洁的语法,希望开发的成本更低,它就适合你.
环境准备: 安装 NodeJs
NodeJs 是 JavaScript 运行时环境,前端开发需要它.
本文帮助你安装 NodeJs 相关环境.
打开 NodeJs下载页面, 下载Windows LTS版本.
如果需要下载 NodeJs特定版本, 点击进入.
下载后安装,全部默认下一步即可.
查看 NodeJs 版本
执行命令:
node -v
如果显示以下提示,则说明安装成功.
查看 NPM 版本
NPM 是 NodeJs 的包管理器.
安装 NodeJs 会自动安装 NPM.
执行命令:
npm -v
启用 Yarn
Yarn 是一个NPM客户端,比自带的NPM客户端更快,更安全.
Yarn 不再需要单独安装,只需启用即可.
执行命令:
corepack enable
查看 Yarn 版本
yarn -v
如果显示以下提示,则说明安装成功.
配置 Yarn 加速地址
国内直接拉取NPM包十分缓慢,需要配置镜像地址.
配置 Yarn 淘宝镜像
yarn config set registry https://registry.npmmirror.com
yarn config set sass_binary_site https://npmmirror.com/mirrors/node-sass
还原 Yarn 仓库地址
如果需要还原为原始地址, 执行命令:
yarn config delete registry
yarn config delete sass_binary_site
Util UI 快速入门
本文演示Util应用框架 Angular UI 开发的基本流程.
准备
拉取 Util 代码生成项目最新代码.
重要: 务必执行此步骤.
生成 UI 项目基架
打开Util代码生成项目解决方案 Util.Generator.sln .
将项目 Util.Generators.Console 设置为启动项目.
打开 appsettings.json 配置文件,修改 ProjectType 配置项为 UI.
如果需要修改数据库类型,参考 Web API 开发快速入门.
重新生成 Util.Generators.Console 项目, 按 F5 键启动控制台开始生成.
进入 D:\Output\Demo 目录,可以看到生成的 Demo 项目.
运行示例项目
打开示例项目解决方案 Demo.sln.
可以看到,新增了 Demo.Ui 项目.
还原npm包并启动Angular开发服务器
进入 D:\Output\Demo\src\Demo.Ui\ClientApp 目录, 它是 Angular 前端项目目录.
该目录包含 start.ps1 脚本文件,运行该脚本.
.\start.ps1
该脚本的内容很简单,还原npm,然后启动.
Write-Host "install npm..."
yarn --ignore-optional
Write-Host "npm start..."
npm start
如果你手工执行 yarn 命令,请务必添加 --ignore-optional 选项,否则安装可能卡住.
安装过程可能出现如下提示,是否向Google发送Angular项目的统计信息, 输入 N,回车.
Would you like to share pseudonymous usage data about this project with the Angular Team at Google under Google's Privacy Policy at https://policies.google.com/privacy. For more details and how to change this setting, see https://angular.io/analytics.
执行完成, Angular CLI 启动开发服务器, 如下所示.
运行 Demo.Ui 项目
UI 的运行需要访问 API ,下面设置同时启动 Demo.Ui 和 Demo.Api 项目.
右键点击VS解决方案,弹出菜单选择 配置启动项目.
弹出启动配置窗口, 选择 启动项目 -> 多个启动项目, 将 Demo.Ui 和 Demo.Api 项目 设置为 启动 ,点击 确定 按钮.
按 F5 键 启动项目.
UI项目启动界面如下.
生成的UI项目为 Angular 微前端模块项目, 主界面导航菜单和顶部菜单等仅用于开发阶段.
dashboard组件仅用于占位,顶部菜单也做了简化,仅保留多语言切换.
发布后, 由微前端基架项目提供主界面,并延迟加载业务模块.
如果按 F12 键,你会看到一个错误消息.
Shared module is not available for eager consumption
这个错误是由微前端框架提示的, 原因是开发阶段使用了 Angular JIT 编译方式.
该错误消息从 Angular 16 开始出现, 并且对开发没有什么影响, 目前尚未找到消除它的方法.
项目发布使用 Angular AOT 编译方式,所以在发布以后会自动消失.
{{% alert title="提示" color="warning" %}}
API项目可能比UI项目启动慢,这会导致UI无法加载数据,只需等待API项目启动完成,重新刷新一下即可.
编辑学生示例
打开学生示例页面
点击 学生 菜单项,打开示例页面.
生成的界面是一个简单的表格,提供CRUD基础操作.
修改查询条件
查询条件按字段生成,如果字段很多,可能显示很乱.
Student 示例业务模块指向的 Razor 页面位于 Demo.Ui\Pages\Routes\Demos\Student 下.
打开 Index.Query.cshtml, 修改查询条件.
@model StudentQuery
<util-form class="search__form">
<util-row align="Top">
<util-column flex="1 1 0px">
<util-row gutter="24">
<util-column sm="6" xs="24">
<util-input for="Name"/>
</util-column>
<util-column sm="6" xs="24">
<util-input for="Gender"/>
</util-column>
<util-column sm="4" xs="24">
<util-date-picker for="BeginBirthday"/>
</util-column>
<util-column sm="4" xs="24">
<util-date-picker for="EndBirthday"/>
</util-column>
</util-row>
</util-column>
<util-column flex="200px">
<util-row justify="End">
<util-button id="btnQuery" type="Primary" icon="Search" on-click="query(btnQuery)" text-query="true"></util-button>
<util-button id="btnRefresh" icon="Sync" on-click="refresh(btnRefresh)" text-refresh="true"></util-button>
</util-row>
</util-column>
</util-row>
</util-form>
刷新页面.
创建学生示例
点击 创建 按钮,弹出创建学生对话框.
性别 字段应为枚举类型,但生成的代码为 int 类型,需要进行修改.
定义性别枚举
VS 打开领域层项目 Demo.Domain .
添加 Enums 目录, 添加 Gender.cs 文件, 创建 Gender 枚举 .
/// <summary>
/// 性别
/// </summary>
public enum Gender {
/// <summary>
/// 女
/// </summary>
[Description("util.female")]
Female = 1,
/// <summary>
/// 男
/// </summary>
[Description("util.male")]
Male = 2
}
如下图所示.
修改学生实体性别属性类型
VS 打开领域层 Student.Base.cs 文件, 修改 Gender 属性.
/// <summary>
/// 性别
///</summary>
[DisplayName( "性别" )]
public Enums.Gender? Gender { get; set; }
修改学生DTO性别属性类型
VS 打开应用层 Demo.Application 项目 StudentDto.cs 文件, 修改 Gender 属性.
/// <summary>
/// 性别
///</summary>
[Display( Name = "demo.student.gender" )]
public Domain.Enums.Gender? Gender { get; set; }
如下所示.
修改学生编辑页面
VS 打开 Demo.Ui\Pages\Routes\Demos\Student\Edit.cshtml 文件.
修改学生性别组件
删除 性别 输入框.
<util-input for="Gender" />
添加单选按钮,当输入 <util ,就会看到 Ng Zorro 组件提示,选择 util-radio, 如下所示.
表单组件和一些与字段相关的组件支持 for 属性,用于绑定DTO属性,从而获取元数据,帮你自动完成常用设置.
修改学生年龄组件
年龄可以通过出生年月计算,这里只是为了演示数值类型.
年龄是一个数值类型,应该使用数值输入框.
<util-input for="Age" />
修改为
<util-input-number for="Age" />
修改完成,代码如下所示.
@page
@model StudentDto
@*标题*@
<util-page-header2 title-create="demo.student.create" title-update="demo.student.update" auto-breadcrumb="false" sync-title="false"></util-page-header2>
@*表单*@
<util-card borderless="true">
<util-form label-span="4" control-span="20" gutter="16">
<util-input for="Name" />
<util-radio for="Gender"></util-radio>
<util-input-number for="Age" />
<util-date-picker for="Birthday" />
<util-input for="IdCard" />
<util-switch for="Enabled" />
<util-modal-footer>
<util-button on-click="close()" text-cancel="true"></util-button>
<util-button id="btnSubmit" is-submit="true" validate-form="true" type="Primary" on-click="submit(btnSubmit)" text-ok="true"></util-button>
</util-modal-footer>
</util-form>
</util-card>
添加学生身份证验证
下面使用身份证属性来演示如何添加基础验证.
你可以直接在输入框组件上设置验证属性,不过挨个设置比较费力,另外服务端也需要验证.
在DTO属性上设置 DataAnnotations 数据注解是更好的方法.
Util 会查找数据注解并转换成 Ng Zorro 输入框组件的验证属性,由于数据注解可以保护服务端API,所以两端均得到同步验证.
在 StudentDto 类的IdCard属性上添加 [Required] 和 [IdCard] 数据注解.
Required是必填项验证,IdCard是身份证验证.
查看学生示例编辑页
修改结束,重新运行 UI 和 API,打开 创建学生 对话框.
创建学生表单现在已经具备基本功能.
- 姓名 输入框已添加必填项验证
- 性别 显示为单选按钮
- 年龄 显示为数值输入框,只能输入数字
- 出生日期 显示为日期输入框,只能选择日期.
- 身份证 输入框只能输入有效身份证.
- 启用 显示为开关,只能选择布尔值.
- 当验证未通过时, 提交按钮处于禁用状态,不可点击.
提交创建学生表单
下面输入一些正常的数据,并提交创建表单.
创建成功,学生列表显示一条数据.
查看学生详请
点击学生列表 详情 链接, 弹出 学生详情 对话框.
详情页使用 Ng Zorro 描述列表组件,无法直接显示枚举类型,性别显示枚举值 2,需要修改.
StudentDto 添加 GenderDescription 属性,如下所示.
/// <summary>
/// 性别
///</summary>
[Display(Name = "demo.student.gender")]
public string GenderDescription => Gender.Description();
打开 Detail.cshtml 详情页.
<util-descriptions-item for="Gender"></util-descriptions-item>
修改为
<util-descriptions-item for="GenderDescription"></util-descriptions-item>
重新运行 UI 项目,打开学生详请页面,可以看到,性别已经更新.
删除学生示例
点击学生列表 删除 链接, 弹出删除确认提示,点击确定删除学生.
切换语言
点击主界面右上角设置按钮,选择 语言 -> English,切换到英语.
首页如下所示.
编辑页如下所示.
详情页如下所示.
可以看到,Util Angular UI 通过Lambda表达式的封装对多语言的支持几乎是透明的.