手搓低代码表单(三)属性配置区

手搓低代码表单(二)属性配置区

在前一节中,我们实现了表单渲染,但实际开发过程中,表单的属性需要支持修改,比如表单的label,是否禁用disabled,是否展示show-word-limit等等, 对于属性的修改,只需要修改表单项对应schema中定义属性的value值即可,然后实时响应到画布区。

属性配置区我们分为两块:

  • 组件属性编辑区

组件属性编辑区用来配置组件的属性,比如label,labelWidth,showLabel,changeTag,tag,tagIcon,defaultValue,required,layout,span,document,regList等等。

  • 表单属性编辑区

表单属性编辑区用来配置表单的属性,比如size,labelPosition,labelWidth,labelSuffix,hideRequiredAsterisk,disabled,gutter,formBtns,unFocusedComponentBorder等等。

最终要实现的效果图如下:

组件属性编辑区

props数据的绑定

编辑区的组件属性编辑区,我们还是以el-input为例,以下是对el-input的定义:

js 复制代码
  const elInput = {
    __config__: {
       label: '单行文本',
          labelWidth: null,
          showLabel: true,
          changeTag: true,
          tag: 'el-input',
          tagIcon: 'input',
          defaultValue: undefined,
          required: true,
          layout: 'colFormItem',
          span: 24,
          document: 'https://element.eleme.cn/#/zh-CN/component/input',
          // 正则校验规则
          regList: [{
          pattern: '/^1(3|4|5|7|8|9)\d{9}$/',
          message: '手机号格式错误'
       }]
    },
    // 组件的插槽属性
    __slot__: {
       prepend: '',
          append: ''
    },
    __vModel__: 'mobile',
       placeholder: '请输入手机号',
       style: { width: '100%' },
    clearable: true,
       'prefix-icon': 'el-icon-mobile',
       'suffix-icon': '',
       maxlength: 11,
       'show-word-limit': true,
       readonly: false,
       disabled: false
}

这里以label属性为例,在右侧编辑区,我们通过v-model绑定了activeDataactiveData为当前选中组件)的label属性,这样我们就可以实时的修改数据。其他的props属性与之类似。

js 复制代码
<el-form-item v-if="activeData.__config__.label!==undefined" label="标题">
    <el-input v-model="activeData.__config__.label" placeholder="请输入标题" />
</el-form-item>

vModel绑定

vModel绑定如下,也是直接绑定到activeData中定义的__vModel__属性。

js 复制代码
<el-form-item v-if="activeData.__vModel__ !== undefined" label="字段名">
    <el-input v-model="activeData.__vModel__" placeholder="请输入字段名" />
</el-form-item>

举个例子:当我们创建一个用户名的表单项,我们可以给它绑定一个字段名,比如username,当我们在画布区中的用户名表单项中输入xunwukong时,那么xunwukong其实是绑定到了defaultValue上。

插槽属性绑定

插槽的绑定与props属性类似,在el-input中,我们定义了__slot__属性,在绑定的时候,也是通过v-model绑定到activeData中定义的__slot__属性。

js 复制代码
 <el-form-item v-if="activeData.__slot__&&activeData.__slot__.prepend!==undefined" label="前缀">
    <el-input v-model="activeData.__slot__.prepend" placeholder="请输入前缀" />
</el-form-item>
<el-form-item v-if="activeData.__slot__&&activeData.__slot__.append!==undefined" label="后缀">
    <el-input v-model="activeData.__slot__.append" placeholder="请输入后缀" />
</el-form-item>

番外

这里我们仅仅对el-input进行了配置,实际上对于不同的组件,配置也是不同的,我们可以根据需求进行扩展,比如el-select组件,有和el-input公用的属性,也有不同的属性,el-select中有options属性,options在配置的时候,我们就需要支持添加选项,支持修改选项的先后顺序,支持删除选项,这些配置都是和el-select相关的,这里我们也简单举个例子, 如下是el-select的定义:

js 复制代码
const selectComponents = [
    {
       __config__: {
          label: '下拉选择',
          showLabel: true,
          labelWidth: null,
          tag: 'el-select',
          tagIcon: 'select',
          layout: 'colFormItem',
          span: 24,
          required: true,
          regList: [],
          changeTag: true,
          document: 'https://element.eleme.cn/#/zh-CN/component/select'
       },
       __slot__: {
          options: [{
             label: '选项一',
             value: 1
          }, {
             label: '选项二',
             value: 2
          }]
       },
       placeholder: '请选择',
       style: { width: '100%' },
       clearable: true,
       disabled: false,
       filterable: false,
       multiple: false
    }
]

options中配置了下拉选项,在渲染的时候通过遍历options属性,渲染出下拉选项:

js 复制代码
options(h, conf) {
       const list  = []

       conf.__slot__.options.forEach(item => {
          list.push(<el-option label={item.label} value={item.value} disabled={item.disabled}></el-option>)
       })

       return list
    }

如上代码所示,options属性是一个函数,函数接收两个参数,一个是h,一个是confh是createElement的别名,conf是当前选中的组件的配置信息。 在编辑区域中,我们通过v-model绑定到activeData中定义的__slot__属性上:

vue 复制代码
 <template v-if="['el-select'].includes(activeData.__config__.tag)">
  <el-divider>选项</el-divider>
  <draggable
      :list="activeData.__slot__.options"
      :animation="300"
      group="selectItem"
      handle=".option-drag"
  >
    <div v-for="(item, index) in activeData.__slot__.options" :key="index" class="select-item">
      <div class="select-line-icon option-drag">
        <i class="el-icon-s-operation" />
      </div>
      <el-input v-model="item.label" placeholder="选项名" size="small" />
      <el-input :value="item.value" size="small" @input="setOptionValue(item, $event)" placeholder="选项值" />
      <div class="close-btn select-line-icon" @click="activeData.__slot__.options.splice(index, 1)">
        <i class="el-icon-remove-outline" />
      </div>
    </div>
  </draggable>
  <div style="margin-left: 20px;">
    <el-button
        style="padding-bottom: 0"
        icon="el-icon-circle-plus-outline"
        type="text"
        @click="addSelectItem">
      添加选项
    </el-button>
  </div>
  <el-divider />
</template>

在上述代码中,遍历options属性,渲染出下拉选项。同时支持添加选项,删除选项等功能,同时通过draggable组件支持拖拽排序。

表单校验配置

每个表单项可能有对应的校验规则,比如requiredpattern等等,这些属性我们可以通过v-model绑定到activeData中定义的regList属性上。

vue 复制代码
<template v-if="Array.isArray(activeData.__config__.regList)">
  <el-divider>正则校验</el-divider>
  <div
      v-for="(item, index) in activeData.__config__.regList"
      :key="index"
      class="reg-item"
  >
              <span class="close-btn" @click="activeData.__config__.regList.splice(index, 1)">
                <i class="el-icon-close" />
              </span>
    <el-form-item label="表达式">
      <el-input v-model="item.pattern" placeholder="请输入正则" />
    </el-form-item>
    <el-form-item label="错误提示" style="margin-bottom:0">
      <el-input v-model="item.message" placeholder="请输入错误提示" />
    </el-form-item>
  </div>
  <div style="margin-left: 20px">
    <el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg">
      添加规则
    </el-button>
  </div>
</template>

如上所示,regList为一个数组,数组中的每个元素都是一个对象,对象中包含patternmessage两个属性,pattern为正则表达式,message为错误提示。同时我们可以添加新的规则。

表单属性编辑区

表单的属性作用于el-form组件,实现代码也比较简单:

vue 复制代码
<el-form-item label="表单名">
  <el-input v-model="formConf.formRef" placeholder="请输入表单名(ref)" />
</el-form-item>
<el-form-item label="表单模型">
  <el-input v-model="formConf.formModel" placeholder="请输入数据模型" />
</el-form-item>
<el-form-item label="校验模型">
  <el-input v-model="formConf.formRules" placeholder="请输入校验模型" />
</el-form-item>
<el-form-item label="表单尺寸">
  <el-radio-group v-model="formConf.size">
    <el-radio-button label="medium">
      中等
    </el-radio-button>
    <el-radio-button label="small">
      较小
    </el-radio-button>
    <el-radio-button label="mini">
      迷你
    </el-radio-button>
  </el-radio-group>
</el-form-item>

上述代码中我们通过v-model绑定了formConf中的属性,formRefel-form组件的ref属性,formModelel-form组件的model属性,formRulesel-form组件的rules属性,sizeel-form组件的size属性,其他的属性也是类似配置。

表单项的属性配置和表单的配置是不同的,表单项的配置是针对每个组件的,表单的配置是针对整个表单的,最终都是绑定到schema上来实现响应式的。

总结

今天我们把组件的属性编辑区实现完成,到目前为止,我们完成了物料区的开发,画布区的开发,属性编辑区的开发。还有一些功能点没有讲到,比如:画布区的表单项的拖拽,画布区的表单项的删除,画布区的表单项的复制,这些功能点比较简单,都是对画布区数据的增删改,就不细讲了。 我们在后续的文章中,会继续讲到出码的功能。

如果你喜欢我的内容,请点赞评论告诉我,我会努力做得更好!

系列链接:

1. 手搓低代码表单(一)整体设计以及物料区开发

2. 手搓低代码表单(二)画布区开发

相关推荐
To_OC8 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
To_OC8 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic8 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy9 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志9 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble10 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长10 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯11 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜12 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司12 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能