日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/4 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用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-blazorgithub.com

安裝 Nuget 包引用

$ dotnet add package AntDesign.Charts

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

<script src="https://unpkg.com/@antv/g2plot@latest/dist/g2plot.js"></script> <script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script>

在_Imports.razor中加入命名空間

@using AntDesign.Charts

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

<Line Data="data" Config="config" />@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#可不行,他被定義約束的死死的,這就遇到下面兩個問題:

  • 有些配置屬性不可能窮舉所有的屬性定義。

  • 而且作為組件的封裝者不可能無時差的跟進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中使用方法如下(部分代碼)

    <Tabs><TabPane Key="1"><Tab>示例1</Tab><ChildContent><Line Data=data1 Config="config1" OtherConfig="otherConfig1" /></ChildContent></TabPane> </Tabs>@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

    <div @ref="Ref"></div>@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); }

    到目前已經完成絕大部分功能,還有一些功能需要進一步技術攻關,歡迎有興趣的網友共享你們的代碼,項目進度情況如下

    https://github.com/ant-design-blazor/ant-design-charts-blazor/issues/2

    相關連接

    微軟Reactor_SH活動:從 HelloWorld 到 AntDesign,Blazor 將 .NET 帶到現代前端圈

    https://www.bilibili.com/video/BV17z4y1Q7cJwww.bilibili.com

    一套基于 Ant Design 和 Blazor 的企業級組件庫

    https://github.com/ant-design-blazor/ant-design-blazorgithub.com

    如果您在使用的過程中碰到問題,可以通過以下途徑尋求幫助,同時我們也鼓勵資深用戶通過下面的途徑給新人提供幫助。

    總結

    以上是生活随笔為你收集整理的用Blazor技术封装G2Plot实现Charts组件的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。