实现简单的`Blazor`低代码
本篇博客只实现基本的低代码,比如新增组件,动态修改组件参数
创建项目
首先创建一个空的Blazor Server,并且命名LowCode.Web
实现我们还需要引用一个Blazor组件库,由于作者用Masa Blazor比较多所以使用Masa Blazor
安装Masa Blazor
将Masa Blazor添加到项目依赖中
<ItemGroup>
<PackageReference Include="Masa.Blazor" Version="1.0.0-preview.3" />
</ItemGroup>
修改Program.cs文件 增加了builder.Services.AddMasaBlazor();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddMasaBlazor();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
打开_Imports.razor 添加以下代码
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using LowCode.Web
@using Masa.Blazor
@using BlazorComponent
@using LowCode.Web.Components
修改Pages\_Host.cshtml,添加以下代码
@page "/"
@using Microsoft.AspNetCore.Components.Web
@namespace LowCode.Web.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<base href="~/"/>
<link href="css/site.css" rel="stylesheet"/>
<!-- masa blazor css style -->
<link href="_content/Masa.Blazor/css/masa-blazor.min.css" rel="stylesheet"/>
<!--icon file,import need to use-->
<link href="https://cdn.masastack.com/npm/@("@mdi")/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered"/>
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss"></a>
</div>
<script src="_framework/blazor.server.js"></script>
<!--js(should lay the end of file)-->
<script src="_content/BlazorComponent/js/blazor-component.js"></script>
</body>
</html>
修改MainLayout.razor文件
@inherits LayoutComponentBase
<MApp>
@Body
</MApp>
这样就完成安装了Masa Blazor
然后开始写实现
实现低代码组件设计
创建Components文件夹
创建渲染组件Component\Render.razor,添加以下代码
@using LowCode.Web.Components.Options
@RenderFragment
@code{
/// <summary>
/// 渲染组件
/// </summary>
[Parameter]
public RenderFragment RenderFragment { get; set; }
/// <summary>
/// 渲染配置
/// </summary>
public GenerateMButtonOptions GenerateMButtonOptions { get; set; }
/// <summary>
/// 渲染动态代码
/// </summary>
public string Code { get; set; }
}
定义组件库模板 DynamicComponentGenerator.razor,由于cs文件不能razor模板,所以创建razor文件,添加以下代码,以下代码我们添加三个组件模板,
@using LowCode.Web.Components.Options
@code {
public static (RenderFragment, string) GenerateMButton(GenerateMButtonOptions options)
{
// 定义模板默认数据
RenderFragment template = @<MButton Block=options.block
Height=options.height
Width=options.width
Class=@options.Class
Style=@options.Style
Dark=options.dark
Attributes=options.attributes>@options.childContent</MButton>;
// 模板定义代码 (存在问题)
var data = $@"<MButton Block={options.block}
Height={options.height}
Width={options.width}
Class={options.Class}
Style={options.Style}
Dark={options.dark}
Attributes={options.attributes}>{@options.childContent}</MButton>";
return (builder => { builder.AddContent(0, template); }, data);
}
public static (RenderFragment, string) GenerateMCard(GenerateMButtonOptions options)
{
RenderFragment template = @<MCard Height=options.height
Width=options.width
Class=@options.Class
Style=@options.Style
Dark=options.dark
Attributes=options.attributes>@options.childContent</MCard>;
var data = $@"<MCard Height={options.height}
Width={options.width}
Class={options.Class}
Style={options.Style}
Dark={options.dark}
Attributes={options.attributes}>{@options.childContent}</MCard>";
return (builder => { builder.AddContent(0, template); }, data);
}
public static (RenderFragment, string) GenerateMAvatar(GenerateMButtonOptions options)
{
RenderFragment template = @<MAvatar Height=options.height
Width=options.width
Class=@options.Class
Style=@options.Style
Attributes=options.attributes>@options.childContent</MAvatar>;
var data = $@"<MAvatar Height={options.height}
Width={options.width}
Class={options.Class}
Style={options.Style}
Attributes={options.attributes}>{@options.childContent}</MAvatar>";
return (builder => { builder.AddContent(0, template); }, data);
}
}
添加Component\ComponentType.cs 组件枚举
namespace LowCode.Web.Components;
public enum ComponentType
{
MButton,
MCart,
MAvatar
}
添加Component\ComponentLibrary.razor用于显示支持的组件
<div style="height: 100px">
<MButton class="button" OnClick="() => OnClick?.Invoke(ComponentType.MButton)">
<MIcon>
mdi-card
</MIcon>
按钮
</MButton>
<MButton class="button" OnClick="() => OnClick?.Invoke(ComponentType.MCart)">
<MIcon>mdi-id-card</MIcon>
卡片
</MButton>
<MButton class="button" OnClick="() => OnClick?.Invoke(ComponentType.MAvatar)">
<MIcon>mdi-id-card</MIcon>
头像
</MButton>
</div>
@code{
public delegate void OnClickDelegate(ComponentType type);
[Parameter]
public OnClickDelegate? OnClick { get; set; }
}
<style>
.button {
margin: 5px;
}
</style>
新增Component\Options\GenerateMButtonOptions.cs 添加以下代码 ,添加组件时的参数
using BlazorComponent;
using Microsoft.AspNetCore.Components;
namespace LowCode.Web.Components.Options;
public class GenerateMButtonOptions
{
public string? height { get; set; }
public string? width { get; set; }
public bool block { get; set; }
public bool dark { get; set; }
public string Style { get; set; } = string.Empty;
public string Class { get; set; } = string.Empty;
public Dictionary<string, object>? attributes { get; set; } = new();
public RenderFragment? childContent { get; set; }
}
然后修改Pages\Index.razor,
@page "/"
@using LowCode.Web.Components.Options
<MRow NoGutters>
<MCol>
<MCard Class="pa-1"
Outlined
Style="height: 100vh"
tile>
<ComponentLibrary OnClick="CreateOnClick"></ComponentLibrary>
</MCard>
</MCol>
<MCol Order="2"
Cols="12"
Sm="6"
Md="8">
<MCard Class="pa-2"
Outlined
Style="height: 100vh"
tile>
@foreach (var item in Renders)
{
<render @onclick="() => Id = item.Key">
@item.Value.RenderFragment
</render>
}
</MCard>
</MCol>
<MCol Order="3">
<MCard Class="pa-2"
Outlined
Style="height:100vh"
tile>
<MCard>
@*TODO:通过反射实现获取组件参数根据参数类型显示指定组件动态修改参数*@
@foreach (var item in Renders)
{
var options = item.Value.GenerateMButtonOptions;
if (item.Key == Id)
{
<MTextField @bind-Value="options.width" Label="width"></MTextField>
<MTextField @bind-Value="options.height" Label="height"></MTextField>
<MTextField @bind-Value="options.Style" Label="Style"></MTextField>
<MTextField @bind-Value="options.Class" Label="Class"></MTextField>
<MDivider></MDivider>
<MButton OnClick="() => AddOptionsAttribute(options.attributes)" Block>新增扩展参数输入框</MButton>
@foreach (var e in options.attributes)
{
<MTextarea NoResize Rows="1" Value="@e.Key" ValueChanged="(v) => { options.attributes.Remove(e.Key);options.attributes.Add(v,e.Value);}"></MTextarea>
<MTextarea NoResize Rows="1" Value="@options.attributes[e.Key].ToString()" ValueChanged="(v)=>options.attributes[e.Key]= v"></MTextarea>
}
<MButton Block OnClick="()=>DeleteComponent(item.Key)">删除</MButton>
}
}
</MCard>
</MCard>
</MCol>
</MRow>
@code {
public string Id { get; set; }
private Dictionary<string, Render> Renders = new();
private RenderFragment RenderFragment { get; set; }
private void AddOptionsAttribute(Dictionary<string, object> attribute)
{
attribute.Add("new","");
}
private void DeleteComponent(string key)
{
Renders.Remove(key);
}
private void CreateOnClick(ComponentType type)
{
GenerateMButtonOptions options = null;
string code;
switch (type)
{
case ComponentType.MButton:
options = new()
{
childContent = @<span>新建的按钮</span>,
attributes = new Dictionary<string, object>(),
width = "100px",
};
(RenderFragment, code) = DynamicComponentGenerator.GenerateMButton(options);
Renders.Add(Guid.NewGuid().ToString("N"), new Render() { RenderFragment = RenderFragment, GenerateMButtonOptions = options, Code = code });
break;
case ComponentType.MCart:
options = new()
{
childContent = @<MButton>多个按钮</MButton>,
attributes = new Dictionary<string, object>(),
width = "100px",
};
(RenderFragment, code) = DynamicComponentGenerator.GenerateMCard(options);
Renders.Add(Guid.NewGuid().ToString("N"), new Render() { RenderFragment = RenderFragment, GenerateMButtonOptions = options, Code = code });
break;
case ComponentType.MAvatar:
options = new()
{
childContent = @<MImage Src="https://cdn.masastack.com/stack/images/website/masa-blazor/jack.png" Alt="Jack"></MImage>,
attributes = new Dictionary<string, object>(),
width = "100px",
};
(RenderFragment, code) = DynamicComponentGenerator.GenerateMAvatar(options);
Renders.Add(Guid.NewGuid().ToString("N"), new Render() { RenderFragment = RenderFragment, GenerateMButtonOptions = options, Code = code });
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
StateHasChanged();
}
}
这样就实现了整个简单的低代码操作,我们可以使用看看效果,简单了解实现原理
我们定义了组件的模板,这个模板是固定的,通过Blazor提供的双向绑定实现动态修改组件参数,这种方式可能不太适合完整的低代码,但是也是不错的思路,

这个项目还处于Demo阶段,不知道是否有大佬一块研究,研究技术极限,Blazor非常好用,推荐
GitHub
项目是MIT开源,希望大佬一块学习,促进Blazor生态
来着Token的分享
实现简单的`Blazor`低代码的更多相关文章
- 应用场景不同,是无代码和低代码的最大区别 ZT
随着媒体对低代码.无代码等先进技术的持续关注,我们发现大多数人都听说过低代码开发和无代码开发这两个概念,但是对两者之间的区别其实并不清楚.事实上,低代码开发和无代码开发之间存在着很多非常显著的差异,如 ...
- 低代码开发LCDP,Power Apps系列 - 新建泰勒创新中心门户案例
低代码简介 上世纪八十年代,美国就有一些公司和实验室开始了可视化编程的研究,做出了4GL"第四代编程语言",到后来衍生成VPL"Visual Programming La ...
- 低代码开发LCDP,Power Apps系列 - 搭建入职选购电脑设备案例
低代码简介 上世纪八十年代,美国就有一些公司和实验室开始了可视化编程的研究,做出了4GL"第四代编程语言",到后来衍生成VPL"Visual Programming La ...
- 使用WtmPlus低代码平台提高生产力
低代码平台的概念很火爆,产品也是鱼龙混杂. 对于开发人员来说,在使用绝大部分低代码平台的时候都会遇到一个致命的问题:我在上面做的项目无法得到源码,完全黑盒.一旦我的需求平台满足不了,那就是无解. ...
- 基于低代码平台(Low Code Platform)开发中小企业信息化项目
前言:中小企业信息化需求强烈,对于开发中小企业信息化项目的软件工作和程序员来说,如何根据中小企业的特点,快速理解其信息化项目的需求并及时交付项目,是一个值得关注和研讨的话题. 最近几年来,随着全球经济 ...
- 为企业应用开发提速,写给企业IT部门的低代码开发基础知识
简介:应用程序开发长期以来一直是IT部门和业务部门面临的问题. IT部门总是被新的应用程序需求弄得不堪重负.他们不可能完成业务部门想要完成的每一个项目. 同时,业务部门的用户厌倦了等待,并开始完全绕过 ...
- 除了降低成本和加速数字化转型,低代码还能给企业带来什么价值 ZT
翻译自:https://dzone.com/articles/measuring-the-roi-of-low-code-1,有删改 低代码 是一种近些年兴起的企业软件快速开发技术和工具.借助低代码使 ...
- 程序员为什么害怕低代码?ZT
转自:https://www.jianshu.com/p/cd89fe94cd30 低代码 是一种近些年兴起的企业软件快速开发技术和工具.借助低代码使用者无需编码即可完成企业应用的常用功能,少量编码扩 ...
- 从表单驱动到模型驱动,解读低代码开发平台的发展趋势 ZT
原文地址:https://www.grapecity.com.cn/blogs/read-the-trends-of-low-code-development-platforms 随着社会数字化进程的 ...
- 破解“低代码”的4大误区,拥抱低门槛高效率的软件开发新选择 ZT
最近,每个人似乎都在谈论“低代码”.以美国的Outsystems.Kinvey,以及国内的活字格为代表的低代码开发平台,正在风靡整个IT世界.毕竟,能够以最少的编码快速开发应用的想法本身就很吸引人.但 ...
随机推荐
- .NET 7 的 AOT 到底能不能扛反编译?
一:背景 1.讲故事 在B站,公众号上发了一篇 AOT 的文章后,没想到反响还是挺大的,都称赞这个东西能抗反编译,可以让破解难度极大提高,可能有很多朋友对逆向不了解,以为用 ILSpy,Reflect ...
- python3的可迭代对象与迭代器对象
可迭代对象与迭代器对象 通过一段简单的代码来理解这俩个概念 a = [1,2,3,4] for i in a: print(i) 这段代码很简单, 对 a 这个列表进行遍历, 然后打印输出每个元素, ...
- springMVC环境的搭建(一)
概要: MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller). MV ...
- SpringCloud Alibaba(三) - GateWay网关
1.基本环境搭建 1.1 依赖 <!-- Gatway 网关会和springMvc冲突,不能添加web依赖 --> <dependency> <groupId>or ...
- Leetcode-SQL学习计划-SQL入门-1527.患某种疾病的患者【regexp正则表达式匹配】
链接:https://leetcode.cn/problems/patients-with-a-condition/ -- 1527.患某种疾病的患者 -- 链接:https://leetcode.c ...
- 【Java SE进阶】Day08 File类、递归
一.File类 1.概述java.io.File 文件和路径的抽象表示 用于文件和目录的创建.查找和删除等 分类 file--文件 directory--文件夹/目录 path--路径 2.静态成员变 ...
- MIsc writeup
1. 杂项 图片里面有什么 ,附件为一张图片 通过Binwalk查看发现有压缩包,通过foremost分离一下. 打开输出文件,发现里面有两个图片. 00000000.png是原图,00000722. ...
- pycharm 小技巧
ctrl键 + B 查看定义源代码 alt键 + enter键 查看帮助 ctrl键 + shift键 + -号 所有代码隐藏 ctrl键 + shift键 + +号 所有代码展示 ctrl键 + D ...
- PKUSC2022 润摆寄
Day 0 模拟赛的题目竟是 寄 摆 润!预示着我的 PKUSC. Day 1 猜中主角(指九条可怜)原来都是芳文厨 看错时间以为考 \(5h\),于是告诉自己 优势在我可以慢慢做. T1 很显然的 ...
- idea的简单介绍
上一篇博客中只是了解一下java文件是怎么编译的,但是一般来说大家都是使用编程软件来进行开发,我是使用IntelliJ IDEA进行开发的 官网下载IDEA(自行安装哈):地址:https://www ...