用react实现页面动态表单设计器

本文介绍了一款采用flex布局的表单设计器实现思路,着重探讨了如何通过拖拽元素完成表单设计,并介绍了表单元素与数据绑定的方法。文章还讨论了布局树的构建与更新、表单模板的保存方式以及与元数据的交互。

 表单设计器整体思路


1、从数据局出发

2、从表单出发

3、拖动布局

grid布局还是flex布局实现呢?grid布局整体上更明快,flex方便一步步推进,2种方式也许都实现一遍,进行比对后再下结论。

前端形成模板后 怎么保存

保存整个模板?还是把结构分解描述为一个个字段保存到数据库?

从表单出发的页面设计器

数据可以和表单元素绑定:

 (元数据来源:)

既然需要和数据元素绑定,必须有一套元数据描述体系作为支撑。

元数据描述怎么来:

   1、手工维护(不动态生成数据库table)

   2、反射取得数据库表信息(能维护吗)

拖动到右边画布的动作?

通过行、列解决整体布局的问题


可能涉及如下操作dom方法?

1、html5 antd

2、react 操作dom
3、js  操作dom

4、es6 操作dom

5、react  jquery 混用(最好不这样)

用flex布局,Row的主轴设成列 Col的主轴设置成行?

行列交叉进行

整个布局为,左边设置工具栏,中间是画布,右边是属性栏目

整个动态布局背后是个树形结构,render方法,即使根据这个结构形成

全页面采取flex布局,层层嵌套(行、列交互嵌套)

每一个元素都是flex:  行元素必然放在列元素当中

列元素 必然放到行元素当中

每个元素都是flex元素  flex display

row 元素 

  • flex-direction:   column

column 元素:

flex-direction:   row

初始化的时候,只能放row,画布director 方向为column

 (整个布局为,左边设置工具栏,中间是画布,右边是属性栏目)

初始化的时候,只留一个div,这个div不可删除

                                        <Button type="primary" shape="circle"
                                                style={
  
  {display: node.id=="1"? "none": "" }}
                                                size="smaill"  onClick={()=>removeNode(_id)}>
                                            D
                                        </Button>

工具栏:


     工具栏布局后期可能需要改进,按grid 或者flex进行修正?

                <div style={ tool_area }>
                    <PageHeader
                        className="site-page-header"
                         title="工具"
                    />
                    <div style={textAlign}>


                    <IconFont id="rowIcon" type="icon-rows"  onDragStart={onDrop}   draggable="true"></IconFont>
                    </div>

                    <div style={textAlign}>
                        <IconFont id="colIcon" type="icon-column" onDragStart={onDrop}   draggable="true"></IconFont>
                    </div>


                    <div style={textAlign}>
                        <IconFont id="input" type="icon-input"></IconFont>
                    </div>


                    <div style={textAlign}>
                        <IconFont id="input1" type="icon-input1"></IconFont>
                    </div>
                </div>
拖放工具栏的图标,放在目标元素上的时候:
    const drop=(event)=>
    {
        let _id=event.currentTarget.id
        // 根据id找到树种的节点
        //给这个节点赋予新的子节点
        let newLayoutTree = deepCopy(layoutTree);
        let n=queryNode(newLayoutTree,_id);
        if(n==null  || n==undefined){
            return;
        }
        if(n.layoutType==null  || n.layoutType==undefined){
            return;
        }
        if(!(n.layoutType==1  || n.layoutType==2)){
            return;
        }
        let newNode=null;
        let _nodeId = newGuid();
        if(n.layoutType==1){
             newNode = new LayoutTreeNode(_nodeId,_nodeId,n.id,_nodeId,2,1,[]);  //布局树
        }else if(n.layoutType==2){
            newNode = new LayoutTreeNode(_nodeId,_nodeId,n.id,_nodeId,1,1,[]);  //布局树
        }
        n.children.push({...newNode});
        //设置
        console.log(newLayoutTree)
        setLayoutTree(newLayoutTree);
        stopBubbling(event)
    }

      这里需要注意的是,必须对原来的存放在state中的数据。进行deep copy,否则,render的时候,感知不到数据的变化。删除元素的时候,也面临似的问题,同样需要deep copy。

完整代码如下:

//动态表单设计器

import React, {useState} from 'react';
import {Button, Form, Input, message, PageHeader} from 'antd';
import {createFromIconfontCN} from '@ant-design/icons';

const ROW_TYPE=1;   //行类型
const COL_TYPE=2;   //列类型



//export default class Dynamic_Form_Designer2 extends Component {
export default function Dynamic_Form_Designer2(prop) {
    const  [form] = Form.useForm();


    /**flexGrow :flex grow 值**/
    const getRowLayoutStyle=(flexGrow)=>{
        return {flex: flexGrow+" 1 auto",
            // border: "1px solid #cccccc",
            paddingTop:"1em",paddingLeft:"0.3em",paddingRight:"1em",paddingBottom:"1em",
            margin:"0.5em",backgroundColor:"RGB(172,216,230)",boxSizing: "border-box",
            display:"flex",
            flexDirection:"row"
        }
     }

    const getColLayoutStyle=(flexGrow)=>{
        return {
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值