狠狠色噜噜狠狠狠狠2021,久久精品国产亚洲av麻豆白洁,777米奇影视盒,国内精品老年人视频网站

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

去年上線的可視化編輯器 H5-dooring 至今已有一年的時間,期間有很多熱心的網友和大佬提出了非常多寶貴的建議,我們也在一步步實現中,以下是幾個比較典型的低代碼可視化平臺需求:

  • 出碼能力(即源碼下載功能)
  • 組件交互(即組件支持業(yè)務中常用的鏈接跳轉,彈窗交互,自定義事件等)
  • 數據源管理(即用戶創(chuàng)建的不同頁面擁有共享數據的能力,不同組件之間也有共享數據的能力)
  • 組件商店(即用戶可以自主生產組件,定義組件,接入組件數據的能力)
  • 布局能力(即用戶可以選擇不同的布局方案來設計頁面)
  • 常用功能集成(頁面截圖,微信分享,debug能力)

上面的這些功需求已經在 H5-dooring 陸續(xù)實現了,在我之前的文章中也有對應的技術分享。但是為了讓更多的人能低成本的擁有自己的可視化搭建系統(tǒng),我們團隊的大佬花了非常多的時間研究和沉淀,最近也開源了一款可視化搭建框架 dooringx-lib,我們可以基于它輕松制作可視化編輯器,而無需考慮內部的實現細節(jié),接下來我就和大家分享一下這款可視化框架的使用方式和實現思路,同時也非常感謝 dooring可視化團隊 各位大佬們的辛勤付出。

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

dooringx

可視化搭建框架基本使用和技術實現

為了讓大家更好的理解可視化搭建框架,我這里舉幾個形象的例子:

  1. antd —— antd-pro

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

我們都知道 antd 是流行的前端組件庫,那么基于它上層封裝的管理后臺 antd-pro 就是它的上層應用。

  1. GrapesJS —— craft.js

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

GrapesJS 是一款國外的頁面編輯器框架(詳細介紹可參考我之前的文章 這款國外開源框架, 讓你輕松構建自己的頁面編輯器) ,那么 craft.js 就是它的上層應用框架。

  1. dooringx-lib —— dooringx

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

dooringx

dooringx-lib 是一款可視化搭建框架,同理 dooringx 就是基于 dooringx-lib 的可視化編輯器。

之所以要介紹它們的區(qū)別,是因為之前有很多朋友對這塊概念理解的不是很清晰,在了解了可視化搭建框架 的 “內涵” 之后,我們開始今天的核心內容。

1.技術棧

在分享框架實現思路之前當然要自報家門,框架實現上我們還是采用熟悉的 React 生態(tài),移動端組件庫采用的眾安團隊的 zarm,編輯器應用層采用的 antd,至于其他的比如拖拽,參考線,狀態(tài)管理插件機制等都是我們團隊大佬自研的方案。如果你是 vue 或者其他技術棧為主的團隊,也可以參考實現思路,相信也會對你有一定的啟發(fā)。

2.基本使用方式

在開始深入之前我們先看看如何使用這款框架,我們只需要按照如下方式即可安裝使用:

npm/yarn install dooringx-lib

同時我們還提供了基礎的使用demo,方便大家在自己的工程中快速上手:

# 克隆項目# cnpmjsgit clone https://github.com.cnpmjs.org/H5-Dooring/dooringx.git# orgit clone https://github.com/H5-Dooring/dooringx.git# 進入項目目錄cd dooringx# 安裝依賴yarn install# 啟動基礎示例yarn start:example# 啟動 dooringx-libyarn start# 啟動 dooringx doc 文檔yarn start:docyarn build

demogithub 項目如下:

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

github地址: https://github.com/H5-Dooring/dooringx

在了解完使用方式之后,我們來看看基本架構和實現思路。

3.dooringx-lib基礎架構和工作機制

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

上圖就是我根據目前 dooringx-lib 的項目架構梳理的架構圖,基本包含了搭建化編輯框架的大部分必備模塊。為了保證框架的靈活性,我們還可以按需安裝對應的功能組件,開發(fā)自定義的組件等。如下是一個基本的導入案例:

import { RightConfig, Container, useStoreState, innerContainerDragUp, LeftConfig, ContainerWrapper, Control,} from 'dooringx-lib';

我們將整個框架拆分成了不同的模塊,這些模塊既相互獨立又可以相互關聯(lián)。完整的工作流程如下:

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

由上圖可以看出,我們只需要擁有基礎的業(yè)務研發(fā)能力,就可以借助 dooringx-lib 構建一個屬于自己的搭建平臺,就好比任何程序的本質: 數據邏輯。

4.dooringx-lib插件開發(fā)

接下來我會和大家分享 dooringx-lib 的插件開發(fā)方式和具體實現(如何導入插件,如何編寫組件,如何注冊函數等),如果大家感興趣的話也可以跟著下面的方式實踐一下。

4.1 如何導入組件

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

我們在上圖可以看到左側是我們的組件物料區(qū),分為基礎組件,媒體組件,可視化組件,它們的添加會統(tǒng)一放在 LeftRegistMap 數組中來管理,其基本結構如下:

const LeftRegistMap: LeftRegistComponentMapItem[] = [ { type: 'basic', // 組件類別 component: 'button', // 組件名稱 img: 'icon-anniu', // 組件icon displayName: '按鈕', // 組件中文名 urlFn: () => import('./registComponents/button'), // 注冊回調 },];

左側組件支持同步導入或者異步導入。

如果需要異步導入組件,則需要填寫 urlFn,需要一個返回 promise 的函數。也可以支持遠程載入組件,只要 webpack 配上即可。

如果需要同步導入組件,則需要將組件放入配置項的 initComponentCache 中,這樣在載入時便會注冊進 componentRegister 里。

initComponentCache: { modalMask: { component: MmodalMask }, },

4.2 如何定制左側面板

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

左側面板傳入 leftRenderListCategory 即可。

leftRenderListCategory: [ {type: 'basic',icon: <HighlightOutlined />,displayName: '基礎組件', }, {type: 'xxc',icon: <ContainerOutlined />,custom: true,customRender: <div>我是自定義渲染</div>, },],

type 是分類,左側組件顯示在哪個分類由該字段決定。icon 則是左側分類小圖標(如上圖所示)。當 customtrue 時,可以使用 customRender 自定義渲染。

4.3 開發(fā)一個自定義的可視化組件

組件需要導出一個由 ComponentItemFactory 生成的對象:

const MButton = new ComponentItemFactory( 'button', '按鈕', {style: [ createPannelOptions<FormMap, 'input'>('input', { receive: 'text', label: '文字', }),],animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})],actions: [createPannelOptions<FormMap, 'actionButton'>('actionButton', {})], }, {props: { ... text:'x.dooring'// input配置項組件接收的初始值}, }, (data, context, store, config) => {return <ButtonTemp data={data} store={store} context={context} config={config}></ButtonTemp>; }, true);export default MButton;

其中第一個參數為組件注冊名,第二個參數用來展示使用。

第三個參數用來配置右側面板的配置項組件。其中鍵為右側面板的分類,值為配置項組件數組。

第四個參數會配置組件的初始值,特別注意的是,制作組件必須要有初始寬度高度(非由內容撐開),否則會在適配時全選時產生問題。

這個初始值里有很多有用的屬性,比如fixed代表使用固定定位,可以結合配置項更改該值,使得組件可以fixed定位。

還有 canDrag 類似于鎖定命令,鎖定的元素不可拖拽。

初始值里的 rotate 需要個對象,value 代表旋轉角度,canRotate 代表是否可以操作旋轉。(0.7.0版本開始支持)

第五個參數是個函數,你將獲得配置項中的 receive 屬性(暫且都默認該配置為receive)傳來的配置,比如上例中 receive 的是 text,則該函數中 data 里會收到該字段。

context 一般只有 previewedit,用來進行環(huán)境判斷。

config 可以拿到所有數據,用來制作事件時使用。

第六個參數 resize 是為了判斷是否能進行縮放,當為 false 時,無法進行縮放。

第七個參數 needPosition,某些組件移入畫布后會默認采取拖拽的落點,該配置項默認為 true, 就是需要拖拽的位置,為 false 時將使用組件自身 topleft 定位來放置。

4.4 事件注冊

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

  1. 注冊時機

事件可以細分為 注冊時機函數,組件內可以通過 hook 的方式來實現注冊時機:

useDynamicAddEventCenter(pr, `${pr.data.id}-init`, '初始渲染時機'); //注冊名必須帶id 約定!useDynamicAddEventCenter(pr, `${pr.data.id}-click`, '點擊執(zhí)行時機');

useDynamicAddEventCenter 第一個參數是 render 的四個參數組成的對象。第二個參數是注冊的時機名,必須跟 id 相關,這是約定,否則多個組件可能會導致名稱沖突,并且方便查找該時機。

注冊完時機后,我們需要將時機放入對應的觸發(fā)位置上,比如這個 button 的點擊執(zhí)行時機就放到 onclick 中:

<Button onClick={() => {eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config); }}> x.dooring</Button>

其中第一個參數則為注冊的時機名,第二個為 render 函數中最后一個參數 config

  1. 函數注冊

函數由組件拋出,可以加載到事件鏈上。比如,注冊個改變文本函數,那么我可以在任意組件的時機中去調用該函數,從而觸發(fā)該組件改變文本。

函數注冊需要放入 useEffect 中,在組件卸載時需要卸載函數!否則會導致函數越來越多。

useEffect(() => {const functionCenter = eventCenter.getFunctionCenter();const unregist = functionCenter.register( `${pr.data.id} 改變文本函數`, async (ctx, next, config, args, _eventList, iname) => { const userSelect = iname.data; const ctxVal = changeUserValue( userSelect['改變文本數據源'], args, '_changeval', config, ctx ); const text = ctxVal[0]; setText(text); next(); }, [ { name: '改變文本數據源', data: ['ctx', 'input', 'dataSource'], options: { receive: '_changeval', multi: false, }, }, ]);return () => { unregist();};}, []);

函數中參數與配置見后面的函數開發(fā)。

4.5 右側面板開發(fā)

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

為了開發(fā)自定義的右側屬性面板,我們只要將開發(fā)的組件配成一個對象放入 initFormComponents 即可。為了良好的開發(fā)體驗,需要定義個 formMap 類型:

export interface FormBaseType { receive?: string;}export interface FormInputType extends FormBaseType { label: string;}export interface FormActionButtonType {}export interface FormAnimateControlType {}export interface FormMap { input: FormInputType; actionButton: FormActionButtonType; animateControl: FormAnimateControlType;}

formMap 的鍵名就是 initFormComponents 鍵名,formMap 的值對應組件需要收到的值。

input 組件為例,FormInputType 此時有2個屬性: label, receive。

那么在開發(fā)該組件時,props 會收到:

interface MInputProps { data: CreateOptionsRes<FormMap, 'input'>; current: IBlockType; config: UserConfig;}

也就是 dataformMap 類型,而 current 是當前點擊的組件,config 就不用說了。

還記得在左側組件開發(fā)中的第三個參數嗎?這樣就都關聯(lián)起來了:

style: [ createPannelOptions<FormMap, 'input'>('input', { receive: 'text', label: '文字' })],

createPannelOptions 這個函數的泛型里填入對應的組件,將會給收到的配置項良好的提示。

在配置項組件里所要做的就是接收組件傳來的配置項,然后去修改 current 的屬性:

function MInput(props: MInputProps) { const option = useMemo(() => {return props.data?.option || {}; }, [props.data]); return (<Row style={{ padding: '10px 20px' }}> <Col span={6} style={{ lineHeight: '30px' }}> {(option as any)?.label || '文字'}: </Col> <Col span={18}> <Input value={props.current.props[(option as any).receive] || ''} onChange={(e) => { const receive = (option as any).receive; const clonedata = deepCopy(store.getData()); const newblock = clonedata.block.map((v: IBlockType) => { if (v.id === props.current.id) { v.props[receive] = e.target.value; } return v; }); store.setData({ ...clonedata, block: [...newblock] }); }} ></Input> </Col></Row> );}

由于可以很輕松的拿到 store,所以可以在任意地方進行修改數據。

將組件的 value 關聯(lián) current 的屬性,onChange 去修改 store,這樣就完成了個雙向綁定。

注意:如果你的右側組件需要用到 block 以外的屬性,可能需要去判斷是否處于彈窗模式。

4.6 自定義右鍵菜單

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

右鍵菜單可以進行自定義:

// 自定義右鍵const contextMenuState = config.getContextMenuState();const unmountContextMenu = contextMenuState.unmountContextMenu;const commander = config.getCommanderRegister();const ContextMenu = () => { const handleclick = () => {unmountContextMenu(); }; const forceUpdate = useState(0)[1]; contextMenuState.forceUpdate = () => {forceUpdate((pre) => pre 1); }; return (<div style={{ left: contextMenuState.left, top: contextMenuState.top, position: 'fixed', background: 'rgb(24, 23, 23)', }}> <div style={{ width: '100%' }} onClick={() => { commander.exec('redo'); handleclick(); }} > <Button>自定義</Button> </div></div> );};contextMenuState.contextMenu = <ContextMenu></ContextMenu>;

先拿到 contextMenuState,contextMenuState 上有個 unmountContextMenu 是關閉右鍵菜單方法。所以在點擊后需要調用關閉。同時上面的 lefttop 是右鍵的位置。另外,我們還需要在組件內增加強刷,賦值給 forceUpdate,用于在組件移動時進行跟隨。

4.7 表單驗證提交思路

前端:從零開發(fā)一款可視化搭建框架(前端可視化框架有哪些)

表單驗證提交有非常多的做法,因為數據全部是聯(lián)通的,或者直接寫個表單組件也可以。在不使用表單組件時,簡單的做法是為每個輸入組件做個驗證函數與提交函數。這樣是否驗證就取決于用戶的選取,而拋出的輸入可以讓用戶選擇放到哪,并由用戶去命名變量。

在點擊提交按鈕時,調用所有組件的驗證函數與提交函數,使其拋給上下文,再通過上下文聚合函數聚合成對象,最后可以通過發(fā)送函數發(fā)送給對應后端,從而完成整個流程。我們可以在 dooringx 中試下這個demo

另一種方式是可以專門寫個提交按鈕,固定了參數,以及部分規(guī)則,比如規(guī)定在頁面中的所有表單都會被收集提交。

那么我們可以利用數據源,將所有表單輸出內容自動提交給數據源,最后的提交按鈕按數據源規(guī)定格式的key 提取,發(fā)送給后端。

后期規(guī)劃

后期我們還會在產品功能方面持續(xù)迭代優(yōu)化,如果大家有好的建議, 也可以隨時和我們交流, 也歡迎在 github 上積極提 issue

如果大家對可視化搭建或者低代碼/零代碼感興趣,也可以參考我往期的文章或者在評論區(qū)交流你的想法和心得,歡迎一起探索前端真正的技術。

github: dooringx | 快速高效搭建可視化拖拽平臺
團隊:Dooring可視化團隊

更多推薦

  • 如何設計可視化搭建平臺的組件商店?
  • 從零設計可視化大屏搭建引擎
  • 從零使用electron搭建桌面端可視化編輯器Dooring
  • (低代碼)可視化搭建平臺數據源設計剖析
  • 從零搭建一款PC頁面編輯器PC-Dooring
  • 如何搭積木式的快速開發(fā)H5頁面?

版權聲明:本文內容由互聯(lián)網用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發(fā)現本站有涉嫌抄襲侵權/違法違規(guī)的內容, 請發(fā)送郵件至 舉報,一經查實,本站將立刻刪除。

(0)
上一篇 2024年7月5日 下午7:39
下一篇 2024年7月5日 下午7:50

相關推薦