antd designable平臺的組件拖拽功能實現(xiàn)代碼
平臺:designable設(shè)計器
github:designable
1 背景
由于業(yè)務(wù)需求,我們需要實現(xiàn)designable平臺的一個簡易版的組件拖拽功能。

- 拖拽區(qū)域
- 渲染組件列表,包括組件的名稱和icon
- 組件可以拖動
- 放置區(qū)域
- 拖動后的組件可以放置,并且放置區(qū)域的組件依舊存在
- 放置區(qū)域的組件可以正確渲染相應(yīng)樣式,使用formily的schema json渲染
- 放置區(qū)域的組件可以上下移動排序,同時可以進行刪除和編輯操作
2 技術(shù)棧
antd
formily:表單引擎,可以根據(jù)schema json直接渲染表單
react-beautiful-dnd:常用于列表的拖拽,支持排序
react-dnd:拖拽和放置功能,比如上面截圖的組件拖拽
3 組件拖拽和放置
3.1 類型定義
右側(cè)組件類型:id唯一標(biāo)識,scheme存放渲染表單的json文件
export interface ComponentConfig {
id?: string; // 唯一標(biāo)識,隨機生成,且不可更改
key: string; // 表單字段key,用戶可以更改
title: string; // 拖拽區(qū)域的文案,不可更改
component_type: ComponentType; // RN側(cè)的組件標(biāo)識,不可更改
schema: ISchema;
}
export enum ComponentType {
TextInputRow = 'TextInputRow', // 文本輸入框
DateInputRow = 'DateInputRow', // 時間選擇器
CheckBox = 'CheckBox',
}右側(cè)組件列表:
export const ComponentConfigs: ComponentConfig[] = [
{
key: ComponentType.TextInputRow,
schema: {
title: ComponentType.TextInputRow,
type: 'string',
'x-component': 'Input',
'x-decorator': 'FormItem',
'x-rn-component': ComponentType.TextInputRow, // RN側(cè)的組件名稱,必須要保持一致
},
},
{
key: ComponentType.DateInputRow,
schema: {
title: ComponentType.DateInputRow,
type: 'string',
'x-component': 'DatePicker',
'x-decorator': 'FormItem',
'x-rn-component': ComponentType.DateInputRow,
},
},
{
key: ComponentType.CheckBox,
schema: {
title: ComponentType.CheckBox,
type: 'string',
'x-component': 'Checkbox',
'x-decorator': 'FormItem',
'x-rn-component': ComponentType.CheckBox,
},
},
].map((i) => ({ ...i, title: i.key, component_type: i.key }));3.2 拖拽
useDrag:讓DOM實現(xiàn)拖拽能力的構(gòu)子
- 請求參數(shù):
- type: 指定元素的類型,只有 類型相同的元素 才能進行drop操作
- item: 元素在拖拽過程中,描述該對象的數(shù)據(jù)??梢栽趗seDrop中的drop接收到該數(shù)據(jù)
- collect: 返回一個描述狀態(tài)的普通對象,然后返回以注入到組件中。它接收兩個參數(shù),一個DragTargetMonitor實例和拖拽元素描述信息item
- 返回參數(shù):
- 第一個返回值:是一個對象 表示關(guān)聯(lián)在拖拽過程中的變量,需要在傳入useDrag的規(guī)范方法的collect屬性中進行映射綁定, 比如:isDraging, canDrag等
- 第二個返回值: 代表拖拽元素的ref
- 第三個返回值: 代表拖拽元素拖拽后實際操作到的dom
// 用于包裹每一個可以拖拽的組件
export const WrapComponent = (props: DndComponentDndItem) => {
const [, drag] = useDrag(() => ({
type: ItemTypes.CARD,
item: props.config,
// collect中可以監(jiān)控drag狀態(tài)變更,并把狀態(tài)暴露給組件
collect: (monitor) => ({ isDragging: !!monitor.isDragging() }),
}));
return (
<div
style={{
width: 100, // todo: 卡片無法居中
cursor: 'move',
height: 50,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
borderRadius: 4,
}}
ref={drag} // dom元素實例
>
{props.children}
</div>
);
};3.3 放置
- 請求參數(shù):
- type: 指定元素的類型,只有 類型相同的元素 才能進行drop操作
- item: 元素在拖拽過程中,描述該對象的數(shù)據(jù)??梢栽趗seDrop中的drop接收到該數(shù)據(jù)
- collect: 返回一個描述狀態(tài)的普通對象,然后返回以注入到組件中。它接收兩個參數(shù),一個DragTargetMonitor實例和拖拽元素描述信息item
- 返回參數(shù):
- 第一個返回值:是一個對象 表示關(guān)聯(lián)在拖拽過程中的變量,需要在傳入useDrag的規(guī)范方法的collect屬性中進行映射綁定, 比如:isDraging, canDrag等
- 第二個返回值: 代表拖拽元素的ref
- 第三個返回值: 代表拖拽元素拖拽后實際操作到的dom
到此這篇關(guān)于antd designable平臺的組件拖拽功能的文章就介紹到這了,更多相關(guān)antd designable組件拖拽內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
TypeScript中yield和Generator的使用指南
本文主要介紹了TypeScript中Generator與yield的用法,涵蓋其語法、類型定義、典型應(yīng)用場景及注意事項,具有一定的參考價值,感興趣的可以來了解一下2025-08-08
JS格式化數(shù)字(每三位加逗號)的方法總結(jié)
這篇文章總結(jié)了JS格式化數(shù)字(每三位加逗號)的幾種方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
前端技巧之HTTP中POST提交數(shù)據(jù)四種方式
這篇文章主要為大家介紹了前端技巧之HTTP中POST提交數(shù)據(jù)四種方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
javascript中利用數(shù)組實現(xiàn)的循環(huán)隊列代碼
javascript中利用數(shù)組實現(xiàn)的循環(huán)隊列代碼,需要的朋友可以參考下。2010-01-01
使用Bootstrap和Vue實現(xiàn)用戶信息的編輯刪除功能
這篇文章主要介紹了使用Bootstrap和Vue實現(xiàn)用戶信息的編輯刪除功能,需要的朋友可以參考下2017-10-10

