前言自從 LogicFlow 正式開源后,受到的關注比我們想象的要多,。在最開始打算要做 LogicFlow 的時候,,我們花了很多的精力去討論要做一個什么樣的流程可視化庫。其中一個選擇是基于現(xiàn)有的業(yè)務直接實現(xiàn)一個開箱即用,,包括了所有的流程編輯庫常用功能的庫,。但是最終還是沒有選擇這樣做,因為我們當時的背景是:不同的項目中,,在流程圖的外觀,、后臺所需數(shù)據(jù)格式都存在較大的差異。有些項目用的是 activity, 有些是某些團隊自研的流程引擎,。所以我們需要做一個能支持各系統(tǒng)平滑遷移的流程可視化庫,,需要這個庫足夠的靈活,視覺上也要滿足個各系統(tǒng)自己的風格,而且最好是流程圖上的各種功能都可以自按需使用,。 基于插件化的拓展機制配置化 or 插件化,?我們對于如何將 LogicFlow 實現(xiàn)成一個足夠靈活的流程可視化庫存在兩種想法。一種是一切皆可配置,,也就是配置化,。這個是很多可視化庫的做法,最典型的就是 ECharts,,用過 ECharts 的人應該都知道,,它的配置功能特別豐富,幾乎可以做到配置任何圖上的元素的效果,,從而達到業(yè)務開發(fā)者需要的自定義效果,。 但是對于我們來說,配置化為了保持其提供足夠的靈活性,,我們需要在內(nèi)部維護太多的 UI 相關的邏輯,。以一個節(jié)點為例: 如果是采用配置化的方式的話,開發(fā)者傳入的配置大致是: javascript復制代碼{ type: 'rect', icon: 'https:///settings.png', text: '22\n33333',} 我們就需要在內(nèi)部代碼中判斷傳入的參數(shù)是否有 icon,,如果有,,就在左上角顯示 icon。但是有的流程希望自己在左上角顯示的是文本,,我們可能就要再增加一個字段 nodeText 來控制了,。那如果我們想顯示一個圖標在右邊呢?想里面顯示 3 列文本呢,? 總的來說,,配置化雖然對業(yè)務開發(fā)者足夠友好,只需要文檔足夠完善,,庫內(nèi)部兼容的效果足夠多,,就可以達到很好的效果。但是對于我們來說卻是需要付出很大的成本去實現(xiàn)各種效果,,而且很可能因為一些其他情況,,舍棄支持一些不常用的效果。從長遠來看,,這種配置化方案對我們來說還是不夠靈活的,。 另一種方案就是插件化,就是將不斷變化的非核心功能分散到插件中,,避免其與核心代碼耦合,,保持其核心部分代碼簡潔和穩(wěn)定。在插件化方案下,,我們就可以實現(xiàn)一個支持設置 icon 節(jié)點就好了,,至于其它特殊需求的節(jié)點,,就有用戶自己利用自定義機制來實現(xiàn)即可。而且開放到社區(qū)后,,其它開發(fā)者自定義的內(nèi)容也可以當做一個插件,,貢獻到 LogicFlow 中來。 插件化會帶來很多好處:
API 健全性&穩(wěn)定性什么是插件,?插件是在核心程序上遵循其提供出來的接口規(guī)范再次編寫的出來的程序,。插件是不能脫離核心程序單獨存在的,,是一種對核心程序功能的擴展。所以個人覺得插件化最重要的一點就是核心程序的 API 健全性和穩(wěn)定性,。如果我們的 API 不夠完善,,社區(qū)開發(fā)者是無法開發(fā)出符合其需求的插件;如果我們的 API 變化很大,,很有可能導致之前開發(fā)的插件在我們版本升級后就不能用了,,會導致整個 LogicFlow 的社區(qū)生態(tài)混亂。 為了保證 API 的健全性和穩(wěn)定性,,我們做了這些事情:
內(nèi)置插件如果我們只提供表示這圖編輯部分的
LogicFlow 本身只是一個單純的流程圖編輯器,不帶有業(yè)務屬性,。為了更好的易用性,,我們提供了 Bpmn-js 插件,讓使用 bpmn-js 的項目能夠快速替換,。有了 Bpmn 插件后,,直接通過 LogicFlow 裝載 bpmn 插件,這個頁面就表現(xiàn)成為 bpmn-js 了,。 javascript復制代碼import LogicFlow from '@logicflow/core';import { Bpmn } from '@logicflow/extension';LogicFlow.use(Bpmn); LogicFlow 的拓展能力前面提到過,,插件的擴展性是否強大,是看核心程序提供的 API 是否有足夠的擴展性,。LogicFlow 在絕大多數(shù) API 上的設計,,其目標就是支持的拓展能力。我們在 自定義節(jié)點為了提高易用性,,在節(jié)點方面,,LogicFlow 內(nèi)置了基礎節(jié)點,然后在
自定義節(jié)點規(guī)則在某些時候,,我們可能需要控制連線的連接方式,比如 A 節(jié)點不能作為連線的起點,、B 節(jié)點不能作為連線的終點、C 節(jié)點后面必須是 A 節(jié)點等等,。LogicFlow 提供了自定義節(jié)點規(guī)則功能來實現(xiàn)這個需求,。 LogicFlow 內(nèi)部有 javascript復制代碼class CnodeModel extends RectModel { /* ignore other code*/ // 判斷這個節(jié)點的下一個節(jié)點是否符合自定義要求 getConnectedSourceRules(): ConnectRule[] { const rules = super.getConnectedSourceRules(); const gateWayOnlyAsTarget = { message: 'C節(jié)點下一個節(jié)點只能是A節(jié)點', validate: (source: BaseNode, target: BaseNode) => { let isValid = true; if (target.type !== 'a-node ') { isValid = false; } return isValid; }, }; rules.push(gateWayOnlyAsTarget); return rules; } // 判斷這個節(jié)點的上一個節(jié)點是否符合自定義要求 getConnectedTargetRules() {}} 自定義連線自定義連線方案和自定義節(jié)點基本一致,,由基礎連線實現(xiàn)線的絕大部分邏輯,,然后在內(nèi)置連線中實現(xiàn)連線的特殊交互處理,最后再由開發(fā)者基于內(nèi)置連線進行自定義開發(fā),。當然,,由于絕大多數(shù)圖編輯上線的表現(xiàn)形式都只有直線、折線和曲線三種形式,,所以一般開發(fā)者自定義連線都是改變一下樣式(顏色,、虛線)和名字(如Bpmn中連線叫做 自定義屬性一般來說,,對于一個節(jié)點,,我們只需要 LogicFlow 中提供了一個 javascript復制代碼lf.register('custom-process', ({TriangleNode,TriangleModel }) => { class CustomProcessNode extends TriangleNode { static extendKey = 'CustomProcessNode'; getShapeStyle() { const attributes = super.getShapeStyle(); const properties = super.getProperties(); // 判斷自定義屬性customStatus是否為error, // 如果是,則將這個節(jié)點的填充顏色設置為紅色,。 if (properties.customStatus === 'error') { attributes.fill = 'red' } return attributes; } } return { view: CustomProcessNode, model: PolygonNodeModel, };}); 上面的代碼自定義了一個 custom-process 節(jié)點,,當傳入的數(shù)據(jù)中節(jié)點 type 為 custom-process,節(jié)點屬性中 customStatus 為 error 的時候,,流程圖上顯示的就是一個紅色的三角形,。 自定義組件在 LogicFlow 中,除了節(jié)點和連線這種由 svg 渲染的圖形外,,還存在著一些用于圖編輯過程中進行控制的組件,,這些組件 LogicFlow 是通過 html 來實現(xiàn)的(比如菜單、控制面板等),。LogicFlow 開放了在圖上插入 DOM 的能力,,開發(fā)者就可以基于這個能力來實現(xiàn)自定義組件,。 有了在圖上自由插件 DOM 的能力,我們就可以做很多事情了,,比如可以實現(xiàn)一個自由調(diào)整節(jié)點顏色,、字體大小的工具。這個工具的開發(fā)就只需要按照我們正常前端開發(fā)即可,。然后在監(jiān)聽到用戶選中節(jié)點后,,將這個 DOM 插入到節(jié)點對應的位置旁邊。 主題上面我們提到過可以用自定義節(jié)點來定制任何節(jié)點的外觀,,但是對每個節(jié)點都單獨自定義一次太多麻煩,。LogicFlow 提供了主題功能,來統(tǒng)一設置所以節(jié)點的外觀基礎屬性,。比如我們想讓所有的矩形都不帶邊框,。 javascript復制代碼lf.setTheme({ rect: { strokeWidth: 0 },}) 主題除了可以設置節(jié)點和連線的外觀以外,還可以設置內(nèi)部功能的樣式,,比如文本,、對齊線等。 最后通過上面的介紹,,大家對 LogicFlow 的拓展機制應該有了一定的了解,。LogicFlow 本身不是一個專門處理某個場景的流程設計工具,而是一個流程圖編輯庫,。大多數(shù)情況下,,拓展性強就意味著無法開箱即用,為了讓 LogicFlow 成為一個開箱即用的庫,,LogicFlow 采用了插件化的機制,,通過插件,將場景限定到實際業(yè)務場景中來,。 LogicFlow 還是一個很新的開源項目,,提供的插件還不夠豐富,也存在業(yè)務場景考慮不周的情況,,歡迎大家在 github 上提 issue,,我們一定會認真對待每一個 issue!LogicFlow 也在尋找 contributor ,,如果你感興趣的話,,歡迎一起來共建! |
|