最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 一天撸一个vue表单生成器 | 创作者训练营

    正文概述 掘金(前端每日一学)   2020-12-27   548

    引言

    最近发现各大厂/小厂 都在搞自己的表单生成器/低代码平台,以提高开发的工作效率,此文将带着大家写一个初版的vue表单生成器。

    demo链接 sutianbinde.github.io/vue-form-re…

    github源码 github.com/sutianbinde…

    建议快速阅读5-10分钟,跟随开发时间3~5小时

    ---

    实现

    1、使用vue-cli生成项目 (对于非本文技术点的步骤,下面就简写了)

    我们示例工程用的 vue2.x版本

    2、安装element 、 sass-loader、sass,并启动项目

    此demo以element为基础渲染组件,后续再升级支持别的库。

    3、借助element ui实现基础布局

    一天撸一个vue表单生成器 | 创作者训练营

    这里主要组件 分为左中右 三个组件,我们后续代码也在这三个组件中实现。

    基本目录结构如下:

    一天撸一个vue表单生成器 | 创作者训练营

    4、在Left.vue中,定义基本的表单组件,并渲染成如上图所示的按钮显示

    json格式

    componentList: [
      {
        label: "输入框",
        component: "ElInput"
      },
      {
        label: "选择器",
        component: "ElSelect"
      },
      {
        label: "单选框",
        component: "ElRadio"
      },
      {
        label: "多选框",
        component: "ElCheckbox"  
    },
      {
        label: "日期选择器",
        component: "ElDatePicker"
      }
    ]
    

    5、当点击或拖拽结束的时候,向middle.vue组件传递组件名称,并生成组件schema数据。

    组件schema数据示例如下,

          componentData: [
            {
              component: "ElSelect", // 组件名称
              label: "表单label",
              $id: "ElSelect_" + Math.floor(Math.random() * 1000), // 未来获取表单v-model数据的key
              propValue: { //需要绑定到表单组件上的props
                value: "", // demo中绑定v-model的key。
                enums: ["a", "b", "c"], // 选项的值
                enumNames: ["早", "中", "晚"] // 选项的名称
              }
            },
            { 
              component: "ElRadio",
              label: "表单label",
              $id: "ElRadio_" + Math.floor(Math.random() * 1000),
              propValue: {
                value: "",
                enums: ["a", "b", "c"],
                enumNames: ["早", "中", "晚"]
              }
            }
          ],
    

    拿到上面数据,我们如何渲染成表单组件呢,这里使用vue 的 component组件进行渲染,即可渲染出对应的组件

      <component
        :is="item.component"
        v-bind="item.propValue"
        v-model="item.propValue.value"  />
    

    但是,element的一些表单组件是多标签使用的,单标签并不能渲染出完整组件,这时候,就需要我们重写这些组件,比如ElSelect组件,这样在渲染的时候就会渲染成我们重写的组件。

    重写策略为:1、继承并传递所有props,2、响应所有事件,3、按照schema数据中的 enums 和 enumNames 生成选项

    我们新建一个文件夹 widgets 用来编写需要重新的组件。示例项目中,我们只重写了两个组件。

    一天撸一个vue表单生成器 | 创作者训练营

    Select.vue的重写代码示例

    <script>
    import { Select } from "element-ui";
    export default {
      props: {
        enums: {
          type: Array,
          default: () => []
        },
        enumNames: {
          type: Array,
          default: () => []
        }, 
       ...Select.props
      },
      render() {
        return (
          <el-select {...{ props: this.$props, on: this.$listeners }}>
            {this.enums.map((val, index) => {
              return <el-option value={val} label={this.enumNames[index]} />;
            })}
          </el-select>
        );
      }};
    </script><style></style>
    

    然后我们需要在middle.vue中引入并注册这个组件,这样meddle.vue中遇到'ElSelect'组件的时候,就会渲染成重写后的组件了。

    ...
    import ElSelect from "../widgets/select.vue";
    import ElRadio from "../widgets/radio.vue";
    export default {
      components: {
        ElSelect,
        ElRadio
      },
      ...
    

    组件渲染之后,效果如下(组件外的基本布局部分,这里就不列举了)

    一天撸一个vue表单生成器 | 创作者训练营

    6、点击表单的时候,实现选中,删除,复制,移动等功能

    选中:这里我们监听表单item的native点击事件(因为点击整个form-item都要选中,所以不能只监听 表单的点击事件)

    <el-form-item
      :label="item.label"
      @click.native="selectCurComponent($event, item)">
      <component
        :is="item.component"
        v-bind="item.propValue"
        v-model="item.propValue.value"
      />
    </el-form-item>
    

    删除,复制,移动 只需按照schema格式操作componentData数组即可。

    7、根据选中项 实现右侧right.vue中的属性编辑

    通过选中的item对应的component属性,可以获取到element的原始组件,找到该组件,就可以获取所有的props。

    import ElementUI from "element-ui";
    
    // ElementUI中组件key 不包含'El',比如 ElSelect 在 ElementUI对象中的key为 'Select',所以这里截掉了前两位// 如果要适应不同组件库,组件前缀应该是在渲染的时候再加,本文章为了方便,所有都默认加上了El
    
    ElementUI[this.activeItem.component.slice(2).props;
    

    8、处理Select/Radio选项的删除和新增

    我们生成shema的时候默认给选项给了初始值 enums 和 选项的名称 enumNames,

    在right.vue中,我们根据这两个数组,生成两个可以新增选项的下拉框,这样,就可以手动输入选项了,最后以选中项作为结果再设置到middle.vue中此表单数据的schema数据中。

    基本代码示例

    // right.vue中设置数据的时候,将 传递过来的nums赋值给对应的key,this.enumOptions = defaultProps.enums;this.enumValue = defaultProps.enums;this.enumNameOptions = defaultProps.enumNames;this.enumNameValue = defaultProps.enumNames;
    
    // right.vue 中根据这几个值渲染出两个特殊表单
    <div>选项字段:</div><el-select  v-model="enumValue"  multiple  filterable  allow-create  default-first-option  placeholder="请选择"  @change="valueChange('enums', $event)">  <el-option    v-for="item in enumOptions"    :key="item"    :label="item"    :value="item"  ></el-option></el-select><div>选项名称:</div><el-select  v-model="enumNameValue"  multiple  filterable  allow-create  default-first-option  placeholder="请选择"  @change="valueChange('enumNames', $event)">  <el-option    v-for="item in enumNameOptions"    :key="item"    :label="item"    :value="item"  ></el-option></el-select>
    
    // right.vue 数据变化的时候触发改变事件
    valueChange(key, value) {  this.$emit("change", key, value);}
    
    // app.vue中接收到change事件,并调用middle.vue中的方法
    
    // 在middle.vue中更改对应的值
    changeProps(key, value) {  this.$set(this.activeItem.propValue, key, value);}
    

    9、right.vue普通props我们这里简单处理成input 和 checkbox,渲染之后,监听input 和change事件,然后去改变middle.vue中对应组件schema数据中的propValue即可。

    基本流程同 8

    10、schema的查看和复制。

    生成用于生产环境的schema应该包括两个部分,一部分为表单数据,另一部分用于绑定v-model,数据示例如下

    {
      "schema": [
        {
          "component": "ElSelect",
          "label": "表单label",
          "$id": "ElSelect_944",
          "propValue": {
            "enums": [
              "a",
              "b",
              "c"
            ],
            "enumNames": [
              "早",
              "中",
              "晚"
            ]
          }
        },
        {
          "component": "ElRadio",
          "label": "表单label",
          "$id": "ElRadio_609",
          "propValue": {
            "enums": [
              "a",
              "b",
              "c"
            ],
            "enumNames": [
              "早",
              "中",
              "晚"
            ]
          }
        }
      ],
      "model": {
        "ElSelect_944": "",
        "ElRadio_609": ""
      }
    }
    

    demo示例中是将schema数据直接放到pre标签中展示,利用document.execCommand("copy")进行复制。

    逻辑比较交单,可去仓库代码中查看。

    11、schema生成之后,如何使用。

    我们需要编写一个通用的render组件,在实际项目中,只要传入schema数据,即可生成对应表单,期待使用方式如下

    <render-components
      :componentData="schema" // 表单渲染数据
      :model="model"  // 表单绑定的值></render-components>
    

    12、根据这种使用方式编写render-components组件。基本逻辑就是使用components组件将表单schema遍历渲染出表单,内部注册覆盖的组件,绑定对应的v-model。

    <template>
      <el-form
        ref="ruleForm"
        label-width="100px"
        class="demo-ruleForm"
        :model="model"
      >
        <el-form-item
          v-for="(item, index) in componentData"
          :key="index"
          :label="item.label"
        >
          <component
            :is="item.component"
            v-bind="item.propValue"
            v-model="model[item.$id]"
          />
        </el-form-item>
      </el-form>
    </template>
    <script>
    import ElSelect from "../widgets/select.vue";
    import ElRadio from "../widgets/radio.vue";
    export default {
      components: {
        ElSelect,
        ElRadio
      },
      props: {
        componentData: {
          type: Array,
          default: () => []
        },
        model: {
          type: Object,
          default: () => ({})
        }
      }};
    </script>
    <style lang="scss" scoped>.demo-ruleForm {  flex: 1;}</style>
    

    后续计划...

    上面只是实现了一个demo版本的表单生成器,如果要正在用于实际生产环境,需要重新规划组织结构、验证schema格式、分组件库实现不同的渲染逻辑、实现表单内部联动逻辑及验证机制、另外还需要提供第三方注册api等。可能会另起一个工程实现pro版。

    文章标题XXX | 创作者训练营 征文活动正在进行中......


    起源地下载网 » 一天撸一个vue表单生成器 | 创作者训练营

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元