律师事务所网站制作,广告公司怎么宣传自己,网站备案照片 多少钱,萍乡建网站平台#xff1a;designable设计器 github#xff1a;designable 目录 1 背景2 技术栈3 组件拖拽和放置3.1 类型定义3.2 拖拽3.3 放置 1 背景
由于业务需求#xff0c;我们需要实现designable平台的一个简易版的组件拖拽功能。 #mermaid-svg-QrxSDGe9YyGG3LbQ {font-family:… 平台designable设计器 githubdesignable 目录 1 背景2 技术栈3 组件拖拽和放置3.1 类型定义3.2 拖拽3.3 放置 1 背景
由于业务需求我们需要实现designable平台的一个简易版的组件拖拽功能。 #mermaid-svg-QrxSDGe9YyGG3LbQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .error-icon{fill:#552222;}#mermaid-svg-QrxSDGe9YyGG3LbQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QrxSDGe9YyGG3LbQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .marker.cross{stroke:#333333;}#mermaid-svg-QrxSDGe9YyGG3LbQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QrxSDGe9YyGG3LbQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .cluster-label text{fill:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .cluster-label span{color:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .label text,#mermaid-svg-QrxSDGe9YyGG3LbQ span{fill:#333;color:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .node rect,#mermaid-svg-QrxSDGe9YyGG3LbQ .node circle,#mermaid-svg-QrxSDGe9YyGG3LbQ .node ellipse,#mermaid-svg-QrxSDGe9YyGG3LbQ .node polygon,#mermaid-svg-QrxSDGe9YyGG3LbQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QrxSDGe9YyGG3LbQ .node .label{text-align:center;}#mermaid-svg-QrxSDGe9YyGG3LbQ .node.clickable{cursor:pointer;}#mermaid-svg-QrxSDGe9YyGG3LbQ .arrowheadPath{fill:#333333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QrxSDGe9YyGG3LbQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-QrxSDGe9YyGG3LbQ .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-QrxSDGe9YyGG3LbQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QrxSDGe9YyGG3LbQ .cluster text{fill:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ .cluster span{color:#333;}#mermaid-svg-QrxSDGe9YyGG3LbQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QrxSDGe9YyGG3LbQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 拖动组件 放置到放置区域 获取当前组件的类别和schema json 在放置区域渲染当前组件 功能列表
拖拽区域 渲染组件列表包括组件的名称和icon组件可以拖动 放置区域 拖动后的组件可以放置并且放置区域的组件依旧存在放置区域的组件可以正确渲染相应样式使用formily的schema json渲染放置区域的组件可以上下移动排序同时可以进行删除和编辑操作
2 技术栈
antd formily表单引擎可以根据schema json直接渲染表单 react-beautiful-dnd常用于列表的拖拽支持排序 react-dnd拖拽和放置功能比如上面截图的组件拖拽
3 组件拖拽和放置
3.1 类型定义
右侧组件类型id唯一标识scheme存放渲染表单的json文件
export interface ComponentConfig {id?: string; // 唯一标识随机生成且不可更改key: string; // 表单字段key用户可以更改title: string; // 拖拽区域的文案不可更改component_type: ComponentType; // RN侧的组件标识不可更改schema: ISchema;
}export enum ComponentType {TextInputRow TextInputRow, // 文本输入框DateInputRow DateInputRow, // 时间选择器CheckBox CheckBox,
}右侧组件列表
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侧的组件名称必须要保持一致},},{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实现拖拽能力的构子
请求参数 type: 指定元素的类型只有 类型相同的元素 才能进行drop操作item: 元素在拖拽过程中描述该对象的数据。可以在useDrop中的drop接收到该数据collect: 返回一个描述状态的普通对象然后返回以注入到组件中。它接收两个参数一个DragTargetMonitor实例和拖拽元素描述信息item 返回参数 第一个返回值是一个对象 表示关联在拖拽过程中的变量需要在传入useDrag的规范方法的collect属性中进行映射绑定, 比如isDraging, canDrag等第二个返回值: 代表拖拽元素的ref第三个返回值: 代表拖拽元素拖拽后实际操作到的dom
// 用于包裹每一个可以拖拽的组件
export const WrapComponent (props: DndComponentDndItem) {const [, drag] useDrag(() ({type: ItemTypes.CARD,item: props.config,// collect中可以监控drag状态变更并把状态暴露给组件collect: (monitor) ({ isDragging: !!monitor.isDragging() }),}));return (divstyle{{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 放置
useDrop让拖拽物放置的构子
请求参数 type: 指定元素的类型只有 类型相同的元素 才能进行drop操作item: 元素在拖拽过程中描述该对象的数据。可以在useDrop中的drop接收到该数据collect: 返回一个描述状态的普通对象然后返回以注入到组件中。它接收两个参数一个DragTargetMonitor实例和拖拽元素描述信息item 返回参数 第一个返回值是一个对象 表示关联在拖拽过程中的变量需要在传入useDrag的规范方法的collect属性中进行映射绑定, 比如isDraging, canDrag等第二个返回值: 代表拖拽元素的ref第三个返回值: 代表拖拽元素拖拽后实际操作到的dom