日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
從零開發(fā)一款可視化搭建框架Dooringx-Lib

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

公司主營業(yè)務(wù):成都做網(wǎng)站、成都網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)建站是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)建站推出廣陽免費(fèi)做網(wǎng)站回饋大家。

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

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

可視化搭建框架基本使用和技術(shù)實(shí)現(xiàn)

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

antd —— antd-pro

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

GrapesJS —— craft.js

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

dooringx-lib —— dooringx

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

之所以要介紹它們的區(qū)別,是因?yàn)橹坝泻芏嗯笥褜@塊概念理解的不是很清晰,在了解了可視化搭建框架 的 “內(nèi)涵” 之后,我們開始今天的核心內(nèi)容。

1.技術(shù)棧

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

2.基本使用方式

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

 
 
 
 
  1. npm/yarn install dooringx-lib

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

 
 
 
 
  1. # 克隆項(xiàng)目
  2. # cnpmjs
  3. git clone https://github.com.cnpmjs.org/H5-Dooring/dooringx.git
  4. # or
  5. git clone https://github.com/H5-Dooring/dooringx.git
  6. # 進(jìn)入項(xiàng)目目錄
  7. cd dooringx
  8. # 安裝依賴
  9. yarn install
  10. # 啟動基礎(chǔ)示例
  11. yarn start:example
  12. # 啟動 dooringx-lib
  13. yarn start
  14. # 啟動 dooringx doc 文檔
  15. yarn start:doc
  16. yarn build

demo 的 github 項(xiàng)目如下:

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

在了解完使用方式之后,我們來看看基本架構(gòu)和實(shí)現(xiàn)思路。

3.dooringx-lib基礎(chǔ)架構(gòu)和工作機(jī)制

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

 
 
 
 
  1. import {
  2.     RightConfig,
  3.     Container,
  4.     useStoreState,
  5.     innerContainerDragUp,
  6.     LeftConfig,
  7.     ContainerWrapper,
  8.     Control,
  9. } from 'dooringx-lib';

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

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

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

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

4.1 如何導(dǎo)入組件

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

 
 
 
 
  1. const LeftRegistMap: LeftRegistComponentMapItem[] = [
  2.   {
  3.       type: 'basic', // 組件類別
  4.       component: 'button', // 組件名稱
  5.       img: 'icon-anniu', // 組件icon
  6.       displayName: '按鈕', // 組件中文名
  7.       urlFn: () => import('./registComponents/button'),  // 注冊回調(diào)
  8.   },
  9. ];

左側(cè)組件支持同步導(dǎo)入或者異步導(dǎo)入。

如果需要異步導(dǎo)入組件,則需要填寫 urlFn,需要一個(gè)返回 promise 的函數(shù)。也可以支持遠(yuǎn)程載入組件,只要 webpack 配上即可。

如果需要同步導(dǎo)入組件,則需要將組件放入配置項(xiàng)的 initComponentCache 中,這樣在載入時(shí)便會注冊進(jìn) componentRegister 里。

 
 
 
 
  1. initComponentCache: {
  2.   modalMask: { component: MmodalMask },  
  3. },

4.2 如何定制左側(cè)面板

左側(cè)面板傳入 leftRenderListCategory 即可。

 
 
 
 
  1. leftRenderListCategory: [
  2.   {
  3. type: 'basic',
  4. icon: ,
  5. displayName: '基礎(chǔ)組件',
  6.   },
  7.   {
  8. type: 'xxc',
  9. icon: ,
  10. custom: true,
  11. customRender: 
    我是自定義渲染
    ,
  12.   },
  13. ],

type 是分類,左側(cè)組件顯示在哪個(gè)分類由該字段決定。icon 則是左側(cè)分類小圖標(biāo)(如上圖所示)。當(dāng) custom 為 true 時(shí),可以使用 customRender 自定義渲染。

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

組件需要導(dǎo)出一個(gè)由 ComponentItemFactory 生成的對象:

 
 
 
 
  1. const MButton = new ComponentItemFactory(
  2.  'button',
  3.  '按鈕',
  4.  {
  5. style: [
  6.  createPannelOptions('input', {
  7.   receive: 'text', 
  8.   label: '文字',
  9.  }),
  10. ],
  11. animate: [createPannelOptions('animateControl', {})],
  12. actions: [createPannelOptions('actionButton', {})],
  13.  },
  14.  {
  15. props: {
  16.  ...
  17.  text:'x.dooring'// input配置項(xiàng)組件接收的初始值
  18. },
  19.  },
  20.  (data, context, store, config) => {
  21. return ;
  22.  },
  23.  true
  24. );
  25. export default MButton;

其中第一個(gè)參數(shù)為組件注冊名,第二個(gè)參數(shù)用來展示使用。

第三個(gè)參數(shù)用來配置右側(cè)面板的配置項(xiàng)組件。其中鍵為右側(cè)面板的分類,值為配置項(xiàng)組件數(shù)組。

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

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

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

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

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

context 一般只有 preview 和 edit,用來進(jìn)行環(huán)境判斷。

config 可以拿到所有數(shù)據(jù),用來制作事件時(shí)使用。

第六個(gè)參數(shù) resize 是為了判斷是否能進(jìn)行縮放,當(dāng)為 false 時(shí),無法進(jìn)行縮放。

第七個(gè)參數(shù) needPosition,某些組件移入畫布后會默認(rèn)采取拖拽的落點(diǎn),該配置項(xiàng)默認(rèn)為 true, 就是需要拖拽的位置,為 false 時(shí)將使用組件自身 top 和 left 定位來放置。

4.4 事件注冊

注冊時(shí)機(jī)

事件可以細(xì)分為 注冊時(shí)機(jī) 和 函數(shù),組件內(nèi)可以通過 hook 的方式來實(shí)現(xiàn)注冊時(shí)機(jī):

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

useDynamicAddEventCenter 第一個(gè)參數(shù)是 render 的四個(gè)參數(shù)組成的對象。第二個(gè)參數(shù)是注冊的時(shí)機(jī)名,必須跟 id 相關(guān),這是約定,否則多個(gè)組件可能會導(dǎo)致名稱沖突,并且方便查找該時(shí)機(jī)。

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

 
 
 
 
  1.     onClick={() => {
  2. eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config);
  3.     }}
  4. >
  5.     x.dooring
  6.  

其中第一個(gè)參數(shù)則為注冊的時(shí)機(jī)名,第二個(gè)為 render 函數(shù)中最后一個(gè)參數(shù) config

函數(shù)注冊

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

函數(shù)注冊需要放入 useEffect 中,在組件卸載時(shí)需要卸載函數(shù)!否則會導(dǎo)致函數(shù)越來越多。

 
 
 
 
  1. useEffect(() => {
  2. const functionCenter = eventCenter.getFunctionCenter();
  3. const unregist = functionCenter.register(
  4.  `${pr.data.id}+改變文本函數(shù)`,
  5.  async (ctx, next, config, args, _eventList, iname) => {
  6.   const userSelect = iname.data;
  7.   const ctxVal = changeUserValue(
  8.    userSelect['改變文本數(shù)據(jù)源'],
  9.    args,
  10.    '_changeval',
  11.    config,
  12.    ctx
  13.   );
  14.   const text = ctxVal[0];
  15.   setText(text);
  16.   next();
  17.  },
  18.  [
  19.   {
  20.    name: '改變文本數(shù)據(jù)源',
  21.    data: ['ctx', 'input', 'dataSource'],
  22.    options: {
  23.     receive: '_changeval',
  24.     multi: false,
  25.    },
  26.   },
  27.  ]
  28. );
  29. return () => {
  30.  unregist();
  31. };
  32. }, []);

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

4.5 右側(cè)面板開發(fā)

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

 
 
 
 
  1. export interface FormBaseType {
  2.     receive?: string;
  3. }
  4. export interface FormInputType extends FormBaseType {
  5.     label: string;
  6. }
  7. export interface FormActionButtonType {}
  8. export interface FormAnimateControlType {}
  9. export interface FormMap {
  10.     input: FormInputType;
  11.     actionButton: FormActionButtonType;
  12.     animateControl: FormAnimateControlType;
  13. }

formMap 的鍵名就是 initFormComponents 鍵名,formMap 的值對應(yīng)組件需要收到的值。

以 input 組件為例,F(xiàn)ormInputType 此時(shí)有2個(gè)屬性: label, receive。

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

 
 
 
 
  1. interface MInputProps {
  2.     data: CreateOptionsRes;
  3.     current: IBlockType;
  4.     config: UserConfig;
  5. }

也就是 data 是 formMap 類型,而 current 是當(dāng)前點(diǎn)擊的組件,config 就不用說了。

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

 
 
 
 
  1. style: [
  2.     createPannelOptions('input', {
  3.         receive: 'text',  
  4.         label: '文字'
  5.     })
  6. ],

createPannelOptions 這個(gè)函數(shù)的泛型里填入對應(yīng)的組件,將會給收到的配置項(xiàng)良好的提示。

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

 
 
 
 
  1. function MInput(props: MInputProps) {
  2.  const option = useMemo(() => {
  3. return props.data?.option || {};
  4.  }, [props.data]);
  5.  return (
  6.  
  7.   {(option as any)?.label || '文字'}:
  8.  
  9.  
  10.             
  11.                 value={props.current.props[(option as any).receive] || ''}
  12.                 onChange={(e) => {
  13.                         const receive = (option as any).receive;
  14.                         const clonedata = deepCopy(store.getData());
  15.                         const newblock = clonedata.block.map((v: IBlockType) => {
  16.                                 if (v.id === props.current.id) {
  17.                                         v.props[receive] = e.target.value;
  18.                                 }
  19.                                 return v;
  20.                         });
  21.                         store.setData({ ...clonedata, block: [...newblock] });
  22.                 }}
  23.             >
  24.  
  25.  );
  26. }

由于可以很輕松的拿到 store,所以可以在任意地方進(jìn)行修改數(shù)據(jù)。

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

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

4.6 自定義右鍵菜單

右鍵菜單可以進(jìn)行自定義:

 
 
 
 
  1. // 自定義右鍵
  2. const contextMenuState = config.getContextMenuState();
  3. const unmountContextMenu = contextMenuState.unmountContextMenu;
  4. const commander = config.getCommanderRegister();
  5. const ContextMenu = () => {
  6.  const handleclick = () => {
  7. unmountContextMenu();
  8.  };
  9.  const forceUpdate = useState(0)[1];
  10.  contextMenuState.forceUpdate = () => {
  11. forceUpdate((pre) => pre + 1);
  12.  };
  13.  return (
  14.  style={{
  15.             left: contextMenuState.left,
  16.             top: contextMenuState.top,
  17.             position: 'fixed',
  18.             background: 'rgb(24, 23, 23)',
  19.  }}
  20. >
  21.  
  22.             style={{ width: '100%' }}
  23.             onClick={() => {
  24.                     commander.exec('redo');
  25.                     handleclick();
  26.             }}
  27.         >
  28.             
  29.  
  •  );
  • };
  • contextMenuState.contextMenu = ;
  • 先拿到 contextMenuState,contextMenuState 上有個(gè) unmountContextMenu 是關(guān)閉右鍵菜單方法。所以在點(diǎn)擊后需要調(diào)用關(guān)閉。同時(shí)上面的 left 和 top 是右鍵的位置。另外,我們還需要在組件內(nèi)增加強(qiáng)刷,賦值給 forceUpdate,用于在組件移動時(shí)進(jìn)行跟隨。

    4.7 表單驗(yàn)證提交思路

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

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

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

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

    后期規(guī)劃

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


    網(wǎng)站題目:從零開發(fā)一款可視化搭建框架Dooringx-Lib
    網(wǎng)頁URL:http://m.5511xx.com/article/dhdcgih.html