1.MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(8)-Ant Design Blazor前端框架搭建
2.blazor组件生命周期
3.使用 SortableJS 组件的 Blazor 可排序列表
4.Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件
5.C#使用WebView2替代Electron
6.一款基于.Net8的可插拔 ERP 和 CRM 系统免费开源了
MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(8)-Ant Design Blazor前端框架搭建
前言
选用Ant Design Blazor作为前端框架搭建ToDoList系统,因其设计规范与风格符合使用经验。此篇将指导如何搭建系统前端。
Ant Design Blazor源码地址:github.com/ant-design-b...
MongoDB从入门到实战相关教程链接
YyFlight.ToDoList项目源码地址:github.com/YSGStudyHard...
安装.NET 7SDK
若本地未安装.NET 7 SDK,需先进行安装,可从dotnet.microsoft.com/en...获取。手机app 源码论坛
新建YyToDoBlazor应用
注意:应用选用Wasm托管模式开发。
AntDesign.Templates:开箱即用的中台前端/设计解决方案,包含丰富组件和布局,适用于构建管理系统。它基于Ant Design Pro框架,并为Blazor项目提供模板和脚手架。
安装AntDesign.Templates模板
在项目目录下,通过cmd打开终端,运行以下命令安装模板:
模板创建 Ant Design Blazor Pro 项目
配置模板参数
BasicLayout.razor 定义网站整体布局,包含导航、菜单、内容和页脚,提供统一风格的页面模板。
预览效果展示
blazor组件生命周期
翻译自: Component lifecycles
blazor组件包含一组虚方法,我们可通过重写这些方法来影响应用行为。这些方法会在组件生命周期的不同阶段执行。以下图展示了生命周期钩子方法的执行流程:
SetParametersAsync 方法在每次父组件渲染时执行。
传递给组件的参数被包含在ParameterView结构体中。这是根据传递到组件的状态对服务器进行异步调用的好时机。
原文:Parameters that were passed into the component are contained in a ParameterView. This is a good point at which to make asynchronous calls to a server (for example) based on the state passed into the component.
在重写的SetParametersAsync中调用base.SetParametersAsync(parameters)时,组件的[Parameter]修饰属性会被赋值。
此方法也适合为参数分配默认值,更多细节请参考 Optional route parameters。
OnInitialized / OnInitializedAsync 方法在为组件的[Parameter]属性赋值后执行。与SetParametersAsync类似,但可以使用组件状态。
这些方法仅在组件创建时执行一次。如果父组件稍后更改了组件的参数,则这些方法会被跳过。
注意:当组件是一个@page时,且Blazor应用在新的URL下重新渲染此@page,Blazor会重用此@page。因为它是同一个对象,Blazor不会调用IDisposable.Dispose方法,也不会执行OnInitialized方法。
这句话我就没有理解明白,我做了一个实验,hashmapput源码一个@page组件有两个路由,一个是/page-one,另一个是/pageone,那么这两个路由来回跳转的话不单单不会执行OnInitialized,其他的方法也不会执行啊。
OnParametersSet / OnParametersSetAsync 方法在组件的新实例中,在OnInitializedAsync之后立即执行。如果它是一个已存在的组件,因为父组件正在重新呈现,所以OnInitialized*方法会被跳过,而这个方法将在SetParametersAsync之后立即执行。
StateHasChanged 方法会标记组件即将被渲染。
当组件希望通知Blazor发生了可能导致呈现输出不同的更改时,将调用此方法。例如,在一个Clock组件中,我们可以设置一个循环的1秒计时器,然后执行StateHasChanged以重新呈现正确的时间。
另一个用途是指导Blazor通过异步方法部分地执行重渲染。
ShouldRender 方法可以通过返回false来阻止组件的RenderTree被重新计算。注意,在第一次创建和呈现组件时,不会执行此方法。
例如,当我们知道我们的状态自上次渲染以来没有改变,或者只是以一种会导致相同输出被渲染的方式改变时,指示Blazor不要经过BuildRenderTree过程可以节省处理时间并改善用户体验。
这个方法不会在组件第一次被渲染的时候执行
BuildRenderTree 方法将应呈现给用户的内容放入内存中(虚拟DOM,即RenderTree)。
上述代码中,向渲染树添加一个h1,内容为“People”。然后它将为people变量中的每个currentPerson局部变量创建一个ShowPersonDetails的新实例。
如果我们的组件在稍后的时间重新渲染,在people中添加一个额外的项,那么ShowPersonDetails组件的一个新实例将被创建并添加到组件的RenderTree中。如果人的条目减少了,那么之前创建的一些ShowPersonDetails组件实例将从组件的RenderTree中被丢弃,如果它们实现了IDisposable, Dispose()将对它们执行。
注意:为了更有效地执行渲染,当在一个循环的上下文中执行渲染时,任何时候都应该添加一个 @key 指令
OnAfterRender / OnAfterRenderAsync 这最后两个方法在Blazor重新生成组件的iapplied源码RenderTree时执行。这可能是由于组件的父组件重新呈现,用户与组件交互(例如鼠标点击),或者组件执行它的StateHasChanged方法来调用重新呈现的结果。
这些方法只有一个名为firstRender的参数。只有在当前组件上第一次调用该方法时,该参数才为true,此后它将始终为false。在需要附加组件连接(例如,通过JavaScript)的情况下,知道这是第一次呈现是很有用的。
只有在OnAfterRender方法执行之后,才可以安全地使用通过@ref指令设置的对组件的引用。
同样的,直到OnAfterRender方法已经执行firstRender设置为true,才可以安全地使用任何通过@ref指令引用的HTML元素集。
Dispose 尽管这不是严格意义上的ComponentBase生命周期方法之一,但如果一个组件实现了IDisposable,那么一旦该组件从其父渲染树中移除,Blazor就会执行Dispose。为了实现IDisposable,我们需要在razor文件中添加@implements IDisposable。
Awaiting within Async lifecycle methods/在异步的生命周期方法中等待
值得注意的是,Blazor将尽可能快地触发渲染,而不是等待长时间运行的异步方法完成后才能呈现组件。
这使得组件能够在执行后台任务(如从服务器检索数据)时为用户呈现内容。
单个方法的等待行为SetParametersAsync
注意:如果重写了该方法,基类的SetParametersAsync方法必须在方法中的任何await指令之前执行,否则将抛出InvalidOperationException。
OnInitializedAsyncOnParametersSetAsyncOnAfterRenderAsync
(记住上述逻辑的一个)简单的规则是SetParametersAsync是唯一不能通过等待任务挂起生命周期进程的方法(观察SetParametersAsync的源码会发现,这个方法中根本就没有await任何东西,所以。。。)。
所有其他异步方法都可以挂起生命周期进程,直到执行退出该方法,而第一个await将导致通过BuildRenderTree进行渲染,以防止用户不得不等待查看更新。
OnRenderAsync可能看起来有些异常,因为它在两种情况下(第一次await时和退出方法时都没有什么动作)都不执行进一步的操作。如果我们考虑到渲染是执行链的最终目标这一事实,那么我们可以将渲染视作是源码110100执行链的最终结果,而不是什么都不做。至于在await上渲染,如果需要,那么程序员必须通过调用StateHasChanged来显式地完成(这个方法中调用StateHasChanged,我实在想不出什么场景能够做这样的操作,关键是容易出现渲染无限循环),否则OnAfterRenderAsync中将导致一个无限循环。
OnAfterRenderAsync这个方法在ComponentBase的源码中它直接了Task.CompletedTask
异步方法和多个await
在async方法中,Blazor执行的代码只会在第一次等待时执行。随后的await不会导致多个渲染。例如
上述例子是原文中的,可能并不好懂,我们来写一个更好懂的:
在上述代码中,如果我没有添加任何StateHasChanged()的话,那么在整个方法结束时页面上会输出_count的值是3,但是中间的变化过程会被忽略掉。
如果我们想要在额外的点上呈现,那么我们必须在所有额外的await语句之前调用StateHasChanged。
有关如何在同一组件上运行不同线程时安全工作的更多信息,请参阅多线程呈现一节。Multi-threaded rendering.
使用 SortableJS 组件的 Blazor 可排序列表
作者:Burke Holland 排版:Alan Wang
在 Web 应用程序中,一个常见功能部分是可排序列表。Blazor 开发者们可能怀念 SortableJS 这个强大的 JavaScript 库。为了填充这个空白,Burke Holland 开发了一个名为 Blazor Sortable 的组件,将其开源在 GitHub 上,供开发者使用。
Blazor Sortable 是一个社区组件,不是 Microsoft 的官方组件,但它提供了一种将 SortableJS 的功能集成到 Blazor 应用中的方法。Fluent UI 团队正在努力在未来版本的 Blazor 中集成可排序组件。
访问演示页面:[提供演示链接]
Burke 和 Jon Galloway,通过“Burke Learns Blazor”直播在 Twitch 和 .NET YouTube 上,共同致力于重建 theurlist.com 应用程序。如果您愿意加入他们的行列,提供帮助,将会非常欢迎。
在 Blazor 中构建可排序列表组件的需求促使 Burke 开发了 Blazor Sortable。SortableJS 提供了丰富的功能,包括排序、列表之间的排序、项目克隆、双星+源码过滤、自定义动画、腰部支持等。
Blazor Sortable 包含了源代码和演示,用户只需要下载 Shared/SortableList.razor、Shared/SortableList.razor.css 和 Shared/SortableList.razor.js 文件。SortableList 组件是一个通用组件,需要提供项目列表和定义如何呈现列表中每个项目的模板。
为了使列表变得可排序,只需处理 OnUpdate 事件并自定义排序逻辑。每当列表排序时,OnUpdate 事件会传递包含已移动项目旧索引和新索引的元组,通过 SortList 方法解构元组并移动列表中的项目。
Blazor Sortable 支持多种功能,如列表之间的排序、克隆项目、过滤项目等。Burke 提供了一个示例,展示了如何在两个列表之间进行排序。
在设置 SortableList 的样式时,您可以覆盖默认样式以适应特定需求。默认样式会隐藏“ghost”元素,产生拖动间隙。您可以修改 SortableItemTemplate 子项内的样式,但必须使用“::deep”修饰符确保样式生效。
HTML5 的原生拖放支持在某些方面有局限性,无法提供理想的排序体验。因此,Blazor Sortable 选择使用 SortableJS 的 JavaScript 解决方案。如果您希望重新启用 HTML5 支持,只需在 SortableList.razor.razor.js 文件中删除 forceFallback: true 属性。
Blazor Sortable 是一个开源社区项目,欢迎开发者探索其功能并提供反馈。Burke 鼓励大家使用 Blazor Sortable 来创建具有高级排序功能的 Blazor 应用程序。您可以通过 GitHub 页面查看 Blazor Sortable 并分享您的想法。
Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件
项目截图 演示地址 演示响应式 感谢szimek撰写的signature_pad.js项目,来自github.com/szimek/signa... 正式开始:在wwwroot/lib目录下,添加signature_pad子文件夹,并下载库文件(文件文末提供源码复制)signature_pad.umd.js,最终版本参照如下。
添加app.js文件。
代码中`wrapperc.invokeMethodAsync("signatureResult", imgBase)`用于回调c#中的签名canvas结果。 js代码 打开Components文件夹,新建SignaturePad.razor.css文件。 打开Components文件夹,新建SignaturePad.razor组件。 参考阅读:Blazor组件参数 组件参数: 在ASP.NET Web Forms中,可以通过公共属性传递参数和数据到控件。这些属性可以在标记中通过特性设置,也可在代码中直接设置。Razor组件以类似方式工作,但组件属性必须使用[Parameter]特性标记才能被视为组件参数。 定义Counter组件,名为IncrementAmount的组件参数,用于指定每次单击按钮时Counter应递增的数量。 定义SaveBaseBtnTitle的组件参数,用于设置或获取[保存为base]按钮的文本。 定义OnResult的组件参数,用于手写签名结果回调。 在Blazor中指定组件参数,像在ASP.NET Web Forms中一样使用特性。 完整代码示例 在Pages文件夹中添加SignaturePadPage.razor文件,用于演示组件调用。 在_Imports.razor中加入引用组件的命名空间。 在首页引用组件演示页或Shared/NavMenu.razor中添加导航。 F5运行程序。 提示:复杂签名可能导致传输数据量大,SSR时可能出现断流显示reload错误,启用以下配置解决此问题。 至此,成功使用JS隔离封装signature_pad签名组件。 Blazor组件自做系列:Blazor组件自做一:使用JS隔离封装viewerjs库
Blazor组件自做二:使用JS隔离制作手写签名组件
Blazor组件自做三:使用JS隔离封装ZXing扫码
Blazor组件自做四:使用JS隔离封装signature_pad签名组件
Blazor组件自做五:使用JS隔离封装Google地图
Blazor组件自做六:使用JS隔离封装Baidu地图
Blazor组件自做七:使用JS隔离制作定位/持续定位组件
Blazor组件自做八:使用JS隔离封装屏幕键盘kioskboard.js组件运行截图
项目源码:Github | GiteeC#使用WebView2替代Electron
C#实现类似Electron的混合桌面程序,可以通过EdgeSharp等库完成。EdgeSharp库可直接使用HTML,并配合Blazor、Razor等前端框架,无需打包整个浏览器内核,打包后的文件体积显著减小。例如,使用EdgeSharp创建的Helloworld程序,仅使用最简单的HTML代码,其打包文件大小仅为1.5M。通过使用EdgeSharp的官方示例,可以进一步发掘其更多强大的功能。在创建Winform程序时,仅保留Program.cs文件,并通过Nuget安装相关依赖。将代码放入Program.cs中,并创建Controller/HelloController.cs文件,继承ActionController并添加ActionController和ActionRoute特性。同时,新建wwwroot/index.html文件,用于与C#后端交互的关键代码。运行项目后,即可得到一个使用HTML作为页面、C#作为后端的桌面程序。此外,提供完整源码下载地址。C#使用WebView2替代Electron/Tauri,同时提供Web核心功能的实现。最后,通过添加系统托盘图标,可将C#项目转换为桌面程序,替代Winform、WPF、Electron、QT、WebView2、Tauri等其他桌面程序。
一款基于.Net8的可插拔 ERP 和 CRM 系统免费开源了
WebVella ERP是一款免费的开放源代码Web软件,致力于满足各类业务数据管理的极致定制和高度可插拔性。该系统基于ASP.NET Core 8、RazorPages和PostgreSQL构建,适用于Linux或Windows操作系统。其显著特点是模块化的设计,用户无需担心系统耦合问题,可以灵活地组合和扩展模块。所有组件均遵循开放标准,便于构建企业级应用。无论是ERP还是CRM,用户均可根据需求定制开发,以实现最优的业务流程。
技术架构亮点提炼效果展示WebVella-ERP源码地址:github.com/WebVella/Web...
asp.netMVC3.0 一个页面做了Layout布局页后,引用的JavaScript和CSS失效了
不要用<script lang="javascript" scr="...."></script>的形式来写,RAZOR应该写成@Scripts.Render("~/Scripts/jquery.js"),这样就能避免路径改变或引用母板页而导致的连接失效问题
css可以用原来的<link>方式,但一定要用“~/”来指定路径!例如:
<link href="~/Content/style.css" type="text/css" rel="stylesheet" />
经典网络结构搜索算法 SPOS,快速完成模型压缩
Single Path One Shot(SPOS)算法是一种高效、低成本的神经网络结构搜索方法,相较于传统的基于强化学习、进化算法等方法,SPOS算法显著降低了搜索成本。MMRazor是一个深度学习模型压缩算法库,支持包括网络结构搜索、剪枝、蒸馏在内的主流技术方向,为OpenMMLab其他算法库提供即插即用、可自由组合的模型压缩算法,使得模型轻量化更为简便快捷。本文将对SPOS算法原理、搜索空间、MMRazor以及在MMRazor中的实现进行详细的解读,内容干货满满。1. SPOS算法介绍
1.1 原理介绍 SPOS算法在ECCV年提出,针对传统NAS算法中网络权重耦合度过高的问题,SPOS提出将网络权重的训练与网络结构的搜索进行解耦。首先训练超网络的权重,然后从超网络中搜索最优的子网络架构,最后对最优子网进行从头开始的训练。整个运行过程分为三个步骤:超网权重训练:使用单路径候选网络构成的超网络,通过优化每层的选择会构建一条单路径子网络。通过优化整个超网的权重完成整个优化过程。
网络结构搜索:从训练好的超网中通过进化算法找到最优的子网络。
重训练子网:在找到最优子网络后,从头开始训练。
1.2 搜索空间介绍 SPOS论文中提到的搜索空间丰富,包括choiceblock搜索、通道搜索和混合精度量化搜索。当前官方源码中仅提供了choiceblock搜索部分。SPOS的搜索空间结构如下表所示,CB代表choiceblock,共包含个CB。CB内部操作主要受ShuffleNetv2启发,提供了四种操作。2. MMRazor简介
MMRazor是一个深度学习模型压缩算法库,支持网络结构搜索、剪枝、蒸馏等主流技术方向,为OpenMMLab其他算法库提供即插即用、可自由组合的模型压缩算法,实现模型轻量化更为简便快捷。MMRazor的整体设计思想与OpenMMLab保持一致,支持多种算法库。其组织架构分为组件层、算法层和应用层。3. MMRazor中超网的构建方式
神经网络结构搜索算法中,超网的实现至关重要。算法框架至少需要具备以下功能:搜索对象是可变化的,如SPOS中的不同候选操作;搜索算法能够指定选择某个候选操作的功能。MMRazor通过引入Mutable和Mutator对象实现上述功能:通过PlaceHolder提供占位符功能,用户定义的可变位置,在调用Mutator中的convert方法后转化为Mutable对象。通过这种方式使超网变成可搜索对象Mutable,后续与Mutator进一步完成NAS任务。4. SPOS在MMRazor中的实现
4.1 环境安装
安装教程请参考:[MMRazor文档链接]。以cuda.1、pytorch1.9为例,首先安装cuda、torch、mmcv包,其中mmcv-full表示采用预编译包的安装方式,还需注意对应cuda以及torch的版本。mmcv安装详细方式以及cuda、torch、mmcv版本对应关系可见:[mmcv文档链接]。以torch1.9为例进行环境安装。 安装MMRazor推荐使用MIM安装或直接使用pip安装:pip install MMRazor。也可以通过源码安装。4.2 Config介绍
由于训练SPOS分为三个阶段,对应三个config: 以spos_supernet_shufflenetv2_8xb_in1k.py为例,config中主要有model、algorithm、mutator三个对象,其中algorithm中包含architecture对象,architecture对象中则包含model。在初始化algorithm的过程中,algorithm会初始化architecture,并根据是否传入mutator、pruner、distiller来决定是否初始化这三个对象。4.3 超网权重训练(Pre-training)
完成以上准备工作后,进行第一个阶段训练:超网权重训练。这个过程需要不断地从超网中采样子网,迭代优化子网参数,最终得到优化后的超网。训练命令如下所示,SPOS中超网训练通过随机采样的方式优化网络,每次前向训练一个batch的过程中会随机采样一个子网络。4.4 网络结构搜索(Evolution search)
此过程初始化候选池,从预训练好的SuperNet中得到Subnet在测试集上的结果,根据得分更新候选池的Topk并执行Mutation和CrossOver操作,得到最优子网的网络结构。训练命令如下所示,这里需要用到上一步超网权重的路径$STEP1_CKPT。具体Searcher选择的是EvolutionSearcher。4.5 重训练子网(Retrain)
在上一步通过进化算法得到最优子网结构后,将其对应的子网络从头进行训练,得到最终的可用网络模型。训练命令如下所示,需要将algorithm.mutable_cfg参数传入,该参数为上一步得到的yaml文件位置。训练过程与训练普通分类网络完全一致。5. 总结
本文详细解读了经典的网络结构搜索算法SPOS及其在MMRazor中的实现流程。SPOS算法能够与各类代码库搭配使用,如与MMDetection库的配合,实现便捷的DetNAS算法。MMRazor不仅包含NAS相关算法,还有蒸馏和剪枝等功能。欢迎体验,如对您有帮助,欢迎点个star。更多内容可查看[相关链接]。