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...获取。反压画线源码
新建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方法。
这句话我就没有理解明白,我做了一个实验,印刷网站源码伪静态源码一个@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重新生成组件的泛滥源码和不泛滥源码区别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时和退出方法时都没有什么动作)都不执行进一步的操作。如果我们考虑到渲染是执行链的最终目标这一事实,那么我们可以将渲染视作是小视频源码自媒体源码执行链的最终结果,而不是什么都不做。至于在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。更多内容可查看[相关链接]。