千家信息网

如何用Blazor技术封装G2Plot实现Charts组件

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这期内容当中小编将会给大家带来有关如何用Blazor技术封装G2Plot实现Charts组件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Blazor是一个使用 .
千家信息网最后更新 2026年11月03日如何用Blazor技术封装G2Plot实现Charts组件

这期内容当中小编将会给大家带来有关如何用Blazor技术封装G2Plot实现Charts组件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Blazor是一个使用 .NET 生成交互式客户端 Web UI 的框架。目前社区刚起步,相关的组件并不多,有幸有一群爱好者正在努力建设社区,我作为社区一员也来贡献一些内容。这里我就分享分享我封装G2Plot后的Blazor组件ant-design-charts-blazor。

ant-design-charts-blazor属于Ant Design of Blazor的一个开源项目,我们的目标是做Ant Design在Blazor生态圈最优秀的实现,废话不多说,先来看一下目前实现的图表。

安装与使用

项目地址:

ant-design-blazor/ant-design-charts-blazor github.com

安装 Nuget 包引用

$ dotnet add package AntDesign.Charts

在wwwroot/index.html(WebAssembly) 或Pages/_Host.razor(Server) 中引入静态文件:


在_Imports.razor中加入命名空间

@using AntDesign.Charts

最后就可以在.razor组件中引用啦!



@code{
object[] data = new object[] {
new { year= "1991", value= 3 },
new { year= "1992", value= 4 },
new { year= "1993", value= 3.5 },
new { year= "1994", value= 5 },
new { year= "1995", value= 4.9 },
new { year= "1996", value= 6 },
new { year= "1997", value= 7 },
new { year= "1998", value= 9 },
new { year= "1999", value= 13 },
};

LineConfig config = new LineConfig()
{
title = new Title()
{
visible = true,
text = "曲线折线图",
},
description = new Description()
{
visible = true,
text = "用平滑的曲线代替折线。",
},
padding = "auto",
forceFit = true,
xField = "year",
yField = "value",
smooth = true,
};
}

组件的使用相对于原先的G2Plot并没有太多变化,主要针对C#语法的特点增加了强类型支持,属性命名规则符合C#语法习惯等。

所以这篇文章不想多聊如何使用的问题,我想谈谈在对G2Plot封装的过程中遇到的一些困难和实现方式,希望能为Blazor社区做出一些绵薄的贡献,如大佬看了有更好的实现方式希望告知在下。

Config对象的封装

G2Plot是通过传入一个Config对象来配置图表的呈现内容,而且只需要给出必要的参数即可,这一切设计的都非常合理。

但是用C#实现的时候就遇上了问题,当Config对象通过InvokeVoidAsync传到JS后,对象会包含所有属性,这对于G2Plot来说就画蛇添足了,有些默认属性会被带进来的空属性给覆盖了,图表显示就出现了问题。

当然最简单的就是把值为Null的属性从Config剔除,嘿嘿,我就是这么干的。通过一个递归遍历对象中的所有属性,移除没有值的属性。

function isEmptyObj(o) {
for (let attr in o) return !1;
return !0
}

function processArray(arr) {
for (let i = arr.length - 1; i >= 0; i--) {
if (arr[i] === null || arr[i] === undefined) arr.splice(i, 1);
else if (typeof arr[i] == 'object') removeNullItem(arr[i], arr, i);
}
return arr.length == 0
}

function proccessObject(o) {
for (let attr in o) {
if (o[attr] === null || o[attr] === undefined) delete o[attr];
else if (typeof o[attr] == 'object') {
removeNullItem(o[attr]);
if (isEmptyObj(o[attr])) delete o[attr];
}
}
}

//清除没有值的项
function removeNullItem(o, arr, i) {
let s = ({}).toString.call(o);
if (s == '[object Array]') {
if (processArray(o) === true) {
if (arr) arr.splice(i, 1);
}
} else if (s == '[object Object]') {
proccessObject(o);
if (arr && isEmptyObj(o)) arr.splice(i, 1);
}
}

一个问题解决了,有一个问题来了,JS/TS是弱类型语言,他对象中的属性可以在实例化时任意添加,C#可不行,他被定义约束的死死的,这就遇到下面两个问题:

  1. 有些配置属性不可能穷举所有的属性定义。

  2. 而且作为组件的封装者不可能无时差的跟进G2Plot对Config定义的变化。

针对这两个问题,我们需要C#中有一个类似的弱类型的对象,这时候我看上了object,它可以定义成任何类型,如果用它做Config参数,可谓是一劳永逸,岂不美哉。

理想是美好的,现实是残酷的。如果用object,那么C#的强类型就彻底丧失,编写图表配置时完全没有提示,基本就是盲写,太恐怖了,C#的优雅荡然无存。

这时突然脑子冒出个念头,为啥不能使用两个配置,一个是强类型的,一个是object,然后将他们合并成最终的配置给到G2Plot,完美。

基本原理就是通过一个递归将传入JS的配置对象挨个对比,并将它们合并,JS实现代码如下

function deepObjectMerge(source, target) {
for (var key in target) {
if (source[key] && source[key].toString() === "[object Object]") {
deepObjectMerge(source[key], target[key])
} else {
source[key] = target[key]
}
}
return source;
}

Blazor中使用方法如下(部分代码)



示例1






@code{
LineConfig config1 = new LineConfig()
{
XField = "date",
YField = "value",
};

object otherConfig1 = new
{
= new object[]
{
new{
Visible = true,
data =new object []{new { date = "2019-05-01", value = 4.9 },new { date = "2019-10-01" } },
Label = new
{
Visible = true,
Field = "festival",
},
},
},
};
}

G2Plot对象方法调用

通过Config生成的图表是静态的,没有生命的死物,我们需要通过调用它的一些函数给予他生命,比如更新配置,更新数据,设置高亮等等。

那么问题就来了,IJSRuntime提供的InvokeAsync方法只能返回可以序列化成json的对象,通过new G2Plot得到的对象不属于此列,我们如何在C#代码中得到G2Plot对象就是个难题了。

好在Blazor提供了一个ElementReference对象给我们,它只能作为Html对象的引用,没法作为JS对象引用,有点可惜,不过它给我们分配了唯一的Id,既然如此,我们就曲线救国。

第一步,得到div的ElementReference



@code{
protected ElementReference Ref;
}

第二步,构造的G2Plot对象,并放到一个叫"chartsContainer"的JS对象中,以Ref.Id作为索引

const plot = new G2Plot[type](domRef, config);
plot.render();
window.AntDesignCharts.chartsContainer[domId] = plot;

第三步,如果需要调用G2Plot对象的方法,那么直接拿着Ref.Id去"chartsContainer"中找到对象后调用,下面是"changeData"方法的实现

changeData(domId, data, all) {
if (window.AntDesignCharts.chartsContainer[domId] == undefined) return;
window.AntDesignCharts.chartsContainer[domId].changeData(data, all);
},

第四步,组件销毁时及时清理"chartsContainer"中不用的对象

public async void Dispose()
await JS.InvokeVoidAsync(InteropDestroy, Ref.Id);
}

到目前已经完成绝大部分功能,还有一些功能需要进一步技术攻关。

上述就是小编为大家分享的如何用Blazor技术封装G2Plot实现Charts组件了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

对象 属性 组件 问题 C# 配置 封装 就是 类型 图表 方法 内容 社区 技术 两个 代码 曲线 功能 参数 方式 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 疫情对互联网科技公司影响 工业互联网科技新基建 互联网金融 科技金融 互联网科技素材视频竖屏 上海电发互联网科技有限公司 团飞科技与伯堂互联网服务平台 崇明区互联网教育科技诚信经营 宜昌元轩互联网科技有限公司 天津腾达互联网科技有限公司 佛山市拉法互联网科技有限公司 高科技互联网发展前景如何 上海京穆互联网科技有限公司 广东工业互联网大赛深圳学泰科技 互联网科技新闻 艺电能源互联网科技有限公司招聘 北京军民互联网科技公司 科技互联网公司两年变化 互联网对科技影响 黑龙江互联网科技公司 颐高云石互联网科技 高科技互联网 互联网科技英文 成都互联网科技公司 佳云科技和互联网广告 搜狐科技互联网 速维有品互联网信息科技(苏州)有限公司 互联网硬科技公司 互联网科技收购价值 互联网科技对化妆品行业 中国主要互联网科技公司
0