element基于el-form智能的FormSmart表单组件

目录
  • 目的
  • 源码
  • 关键文档,大部分复制el-form
    • Attributes
    • Methods
    • Events
    • Slot
    • Scoped Slot
    • Form-Item Attributes
    • Row Attributes
    • Col Attributes
  • 基本用法
  • 使用场景
    • 1. 通用列表搜索条件
    • 2.弹窗写法优化

目的

  • el-form 表单配置化,后期可以利用后端进行配置表单
  • 支持栅格布局
  • el-form 属性大部分都支持
  • 公共配置可以统一处理,如trim、input宽度等
  • 最基本的组件,利用这组件后期可以优化简单的新增编辑弹窗写法

源码

<script>
export default {
    props: {
        model: {
            type: Object,
            default: () => {},
        },
        rowItems: {
            type: Array,
            default: () => [],
        },
        formItems: {
            type: Array,
            default: () => [],
        },
    },
    data() {
        return {
            _model: {},
        };
    },
    mounted() {
        // 用于重置,时间范围选择组件时重置不了endTime
        this._model = { ...this.model };
        // 默认选中光标,设置ref=focus
        this.focus();
    },
    methods: {
        // 处理v-modelv value 值
        hanlderValue(prop) {
            // 时间范围选择组件处理
            if (Array.isArray(prop) && prop.length > 0) {
                const [first] = prop;
                if (this.model[first]) {
                    const data = prop.map((key) => this.model[key]);
                    return data;
                }
                return [];
            }
            return this.model[prop];
        },
        // 处理FormItem绑定值
        hanlderFormItemProp(prop) {
            // 时间范围选择组件处理
            if (Array.isArray(prop) && prop.length > 0) {
                // 处理时间范围选择的
                const [first] = prop;
                return first;
            }
            return prop;
        },
        // 处理改变值
        hanlderModel(prop, value) {
            // 时间范围选择组件处理
            if (prop && Array.isArray(prop)) {
                if (Array.isArray(value)) {
                    // 数组对应值
                    prop.forEach((key, index) => {
                        this.model[key] = value && value.length > 0 ? value[index] : '';
                    });
                } else if ([null, '', undefined].includes(value)) {
                    // 数组有清除按钮时,数组一起清理
                    prop.forEach((key) => {
                        this.model[key] = value;
                    });
                }
            } else {
                this.model[prop] = value;
            }
        },
        focus() {
            this.$nextTick(() => {
                if (this.$refs.focus) {
                    setTimeout(() => {
                        this.$refs.focus.focus();
                    }, 100);
                }
            });
        },
        validate(...props) {
            return this.$refs.form.validate(...props);
        },
        // 对部分字段进行校验
        validateField(...props) {
            return this.$refs.form.validateField(...props);
        },
        // 对整个表单进行重置
        resetFields() {
            Object.assign(this.model, this._model);
            this.$refs.form.resetFields();
        },
        // 移除表单项的校验结果
        clearValidate(...props) {
            this.$refs.form.clearValidate(...props);
        },
    },
    render(createElement) {
        // 父级slots
        // form-item label slot
        const slotLabel = (slotName) => createElement(
            'template',
            {
                slot: 'label',
            },
            this.$slots[slotName],
        );
        // formItem 组件
        const formItem = (item) => createElement(
            'el-form-item',
            {
                props: {
                    ...item,
                    prop: this.hanlderFormItemProp(item.prop),
                },
                scopedSlots: {
                    error: (prop) => this.$scopedSlots[item.slotErrorName] && this.$scopedSlots[item.slotErrorName](prop),
                },
            },
            [
                // 加入label插槽
                item.slotLabelName ? slotLabel(item.slotLabelName) : '',
                // 有插槽优先
                item.slotName ? this.$slots[item.slotName] : createElement(item.type || 'el-input', {
                    //
                    ref: item.ref,
                    attrs: {
                        ...item.props,
                    },
                    props: {
                        clearable: true,
                        ...item.props,
                        value: this.hanlderValue(item.prop),
                    },
                    // 加样式
                    style: {
                        width: '240px',
                        ...(item.props && item.props.style),
                    },
                    on: {
                        ...item.on,
                        change: (value) => {
                            // 重写change方法
                            if (item.on && item.on.change) {
                                item.on.change(value);
                            }
                            this.hanlderModel(item.prop, value);
                        },
                        // el-input 场景
                        input: (value) => {
                            this.hanlderModel(item.prop, value);
                        },
                    },
                }),
            ],
        );
        // col 组件
        const col = (item) => createElement('el-col', {
            props: {
                ...item,
            },
        }, item.formItem ? [formItem(item.formItem)] : '');
        // row组件
        const row = (item) => createElement('el-row', {
            props: {
                ...item,
            },
        }, item.cols.map((list) => col(list)));
        return createElement(
            'el-form',
            {
                ref: 'form',
                props: {
                    ...this.$attrs,
                    model: this.model,
                },
                on: {
                    ...this.$listeners,
                },
            },
            // rowItems 优先
            this.rowItems.length ? this.rowItems.map((item) => row(item)) : this.formItems.map((item) => formItem(item)),
        );
    },
};
</script>

<style lang="scss" module="s"></style>

关键文档,大部分复制el-form

Attributes

参数 说明 类型 可选值 默认值
model 表单数据对象 object
rules 表单验证规则 object
inline 行内表单模式 boolean false
label-position 表单域标签的位置,如果值为 left 或者 right 时,则需要设置 label-width string right/left/top right
label-width 表单域标签的宽度,例如 '50px'。作为 Form 直接子元素的 form-item 会继承该值。支持 auto string
label-suffix 表单域标签的后缀 string
hide-required-asterisk 是否隐藏必填字段的标签旁边的红色星号 boolean false
show-message 是否显示校验错误信息 boolean true
inline-message 是否以行内形式展示校验信息 boolean false
status-icon 是否在输入框中显示校验结果反馈图标 boolean false
validate-on-rule-change 是否在 rules 属性改变后立即触发一次验证 boolean true
size 用于控制该表单内组件的尺寸 string medium / small / mini
disabled 是否禁用该表单内的所有组件。若设置为 true,则表单内组件上的 disabled 属性不再生效 boolean false
-分割线- --- --- --- ---
formItems 表单内组件 array Form-Item
rowItems 表单内组件支持layout布局,优先等级高于formItems array Row Attributes

Methods

方法名 说明 参数
validate 对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promise Function(callback: Function(boolean, object))
validateField 对部分表单字段进行校验的方法 Function(props: array | string, callback: Function(errorMessage: string))
resetFields 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
clearValidate 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果 Function(props: array | string)
focus 使 input 获取焦点 -
blur 使 input 失去焦点,并隐藏下拉框 -

Events

事件名称 说明 回调参数
validate 任一表单项被校验后触发 被校验的表单项 prop 值,校验是否通过,错误消息(如果存在)

Slot

name 说明
label 标签文本的内容

Scoped Slot

name 说明
error 自定义表单校验信息的显示方式,参数为 { error }

Form-Item Attributes

参数 说明 类型 可选值 默认值
prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 string 传入 Form 组件的 model 中的字段
label 标签文本 string
label-width 表单域标签的的宽度,例如 '50px'。支持 auto string
required 是否必填,如不设置,则会根据校验规则自动生成 boolean false
rules 表单验证规则 object
error 表单域验证错误信息, 设置该值会使表单验证状态变为error,并显示该错误信息 string
show-message 是否显示校验错误信息 boolean true
inline-message 以行内形式展示校验信息 boolean false
size 用于控制该表单域下组件的尺寸 string medium / small / mini -

Row Attributes

参数 说明 类型 可选值 默认值
gutter 栅格间隔 number 0
type 布局模式,可选 flex,现代浏览器下有效 string
justify flex 布局下的水平排列方式 string start/end/center/space-around/space-between start
align flex 布局下的垂直排列方式 string top/middle/bottom
tag 自定义元素标签 string * div

Col Attributes

参数 说明 类型 可选值 默认值
span 栅格占据的列数 number 24
offset 栅格左侧的间隔格数 number 0
push 栅格向右移动格数 number 0
pull 栅格向左移动格数 number 0
xs <768px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
sm ≥768px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
md ≥992px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
lg ≥1200px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
xl ≥1920px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
tag 自定义元素标签 string * div

基本用法

demo 直接使用formItems属性来配置表单

<template>
  <div>
    <d-form-smart
      ref="form"
      :model="form"
      label-width="150px"
      label-position="left"
      :form-items="formItems"
    >
      <template #slotErrorName>
        <span>按钮</span>
      </template>
      <template #region-label>
        <el-badge :value="12" class="item">
          <span>自定义label</span>
        </el-badge>
      </template>
      <template #btn>
        <el-button type="primary" @click="submit">提交</el-button>
      </template>
    </d-form-smart>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        form: {
          name: '',
          region: '',
          date: [],
          delivery: false,
          personnel: '',
          radio: '',
          checkbox: [],
          cascader: [],
          timeSelect: '',
          datePicker: '',
          startTime: '',
          endTime: '',
          rate: 0,
          special: '',
          desc: null,
        },
        rules: {
          name: [
            { required: true, message: '请输入活动名称', trigger: 'blur' },
            {
              min: 3,
              max: 5,
              message: '长度在 3 到 5 个字符',
              trigger: 'blur',
            },
          ],
        },
        formItems: [
          {
            label: '名字',
            prop: 'name',
            type: 'el-input',
            props: {
              placeholder: '请输入内容',
            },
          },
          {
            label: '开关',
            prop: 'delivery',
            type: 'el-switch',
          },
          {
            prop: 'region',
            type: 'd-select-smart',
            slotLabelName: 'region-label',
            props: {
              list: [],
            },
          },
          {
            label: '级联',
            prop: 'cascader',
            type: 'el-cascader',
            props: {
              options: [
                {
                  value: 'zhinan',
                  label: '指南',
                  children: [
                    {
                      value: 'shejiyuanze',
                      label: '设计原则',
                      children: [
                        {
                          value: 'yizhi',
                          label: '一致',
                        },
                        {
                          value: 'fankui',
                          label: '反馈',
                        },
                        {
                          value: 'xiaolv',
                          label: '效率',
                        },
                        {
                          value: 'kekong',
                          label: '可控',
                        },
                      ],
                    },
                  ],
                },
              ],
            },
          },
          {
            label: '时间选择',
            prop: 'timeSelect',
            type: 'el-time-select',
            props: {
              placeholder: '选择时间',
            },
          },
          {
            label: '日期选择',
            prop: 'datePicker',
            type: 'el-date-picker',
            props: {
              placeholder: '选择日期',
              valueFormat: 'yyyy-MM-dd',
            },
          },
          {
            label: '日期范围选择',
            prop: ['startTime', 'endTime'],
            type: 'el-date-picker',
            props: {
              type: 'daterange',
              startPlaceholder: '开始日期',
              endPlaceholder: '结束日期',
              format: 'yyyy-MM-dd',
              valueFormat: 'yyyy-MM-dd',
            },
          },
          {
            label: '评分',
            prop: 'rate',
            type: 'el-rate',
          },
          {
            label: '备注',
            prop: 'desc',
            type: 'el-input',
            props: {
              placeholder: '请输入内容',
              type: 'textarea',
              style: {
                width: '400px',
              },
            },
          },
          {
            slotName: 'btn',
            props: {},
          },
        ],
      };
    },
    methods: {
      change(val) {
        console.log('change', val);
      },
      submit(){
           console.log(this.form);
      }
    },
  };
</script>

使用场景

1. 通用列表搜索条件

  • 配置
  queryItems: [
        {
            label: '属性编码',
            prop: 'propertyValueCode',
            props: {
                placeholder: '属性编码',
            },
        },
        {
            label: '属性名称',
            prop: 'name',
            props: {
                placeholder: '属性名称',
            },
        },
    ],
  • 模板写法
    <d-form-smart
        @submit.native.prevent
        ref="query"
        inline
        :model="query"
        label-width="80px"
        label-position="right"
        :form-items="queryItems"
      >
      </d-form-smart>

2.弹窗写法优化

  • 简单的新增
  • form v-model绑定的值
  • rules 规则
  • formItems 表单配置
  async add() {
            try {
                // 重置表单
                Object.assign(this.form, this.$options.data().form);
                this.$msgbox({
                    customClass: ['custom-message-box'],
                    title: '新增属性',
                    message: this.$createElement('FormSmart', {
                        ref: 'form',
                        key: Math.random(), // 重新创建,不缓存
                        attrs: {
                            labelWidth: '100px',
                            labelPosition: 'right',
                            model: this.form,
                            rules: this.opRules,
                            formItems: opItems,
                        },
                    }),
                    closeOnClickModal: false,
                    showCancelButton: true,
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    beforeClose: async (action, instance, done) => {
                        if (action === 'confirm') {
                            await this.$refs.form.validate();
                            instance.confirmButtonLoading = true;
                            try {
                                // 请求接口编写的地方
                                instance.confirmButtonLoading = false;
                                done();
                            } catch (error) {
                                instance.confirmButtonLoading = false;
                            }
                        } else {
                            this.$refs.form.resetFields();
                            done();
                        }
                    },
                });
            } catch (error) {
                console.error(error);
            }
        },

到此这篇关于element基于el-form智能的FormSmart表单组件的文章就介绍到这了,更多相关element FormSmart表单内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • ElementUI实现el-form表单重置功能按钮

    目录 业务场景: 效果演示: 业务场景: 使用el-form时,点击重置按钮或者取消按钮时会实现表单重置效果. 重置功能按钮功能实现详细步骤: 第一:首先给el-form添加ref属性. <el-form :inline="true" :model="queryParams" ref="queryForm"> 第二:在点击重置按钮执行的方法中,执行如下功能代码片段 reset(){ # 重新设置请求参数实体属性 this.queryP

  • element中el-form-item属性prop踩坑

    最近负责前后端项目开发,有个需求是实现Djangorestframework(drf)+element实现动态渲染form表单,drf后端提供json,前端从json中获取form表单元素,并且绑定表单验证规则 在el-form-item属性prop上遇到报错或者没绑定到数据,报错如下 [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'prop')" elemen

  • vue elementui el-form rules动态验证的实例代码详解

    一.介绍 简介:在使用elementUI el-form 中,对于业务不同的时候可能会产生不同表单结构,但是都是存在同一个表单控件el-form中. 图片介绍: 1.在用户选择单选或多选时会有A,B,C,D,E五个选项 2.在用户选择简答题时只会题干,答案以及解析选项(主要是通过v-if来进行判断) 问题引入:当用户选择不同的题库时会产生不同的form表单选项,这个时候在进行表单提交验证的时候就需要根据不同试题类型进行判断,这个时候就需要两个rules来动态进行表单校验. 解决方法:在页面加载的

  • element基于el-form智能的FormSmart表单组件

    目录 目的 源码 关键文档,大部分复制el-form Attributes Methods Events Slot Scoped Slot Form-Item Attributes Row Attributes Col Attributes 基本用法 使用场景 1. 通用列表搜索条件 2.弹窗写法优化 目的 el-form 表单配置化,后期可以利用后端进行配置表单 支持栅格布局 el-form 属性大部分都支持 公共配置可以统一处理,如trim.input宽度等 最基本的组件,利用这组件后期可以

  • Vue2 Element Schema Form 配置式生成表单的实现

    目录 前置知识点 Component $attrs $listeners 表单的结构是什么样的 配置数组数据结构 结语 前置知识点 为了实现一个Schema Form配置式表单的生成,需要了解一部分前置知识点. Component vue 提供了一个内置组件 Component,用来动态渲染组件,举个例子,本篇文章以Element UI 为例,假设我们全局注册了Element UI的组件,那么下面一段代码 <Component is="el-input"></Comp

  • 基于BootStrap与jQuery.validate实现表单提交校验功能

    谈谈表单校验 这大概是一种惯例,学习前台后台最开始接触的业务都是用户注册和登录.现在社会坚持以人为本的理念,在网站开发过程同样如此.User是我们面对较多的对象,也是较核心的对象.最开始的用户注册和登陆这块,也就尤为重要. 直接看demo:http://www.suchso.com/code/bootstrapvalidate/ 用户注册和登录其实往往比我们想象的难.就比如表单校验,里面涵盖的内容其实挺多,就前台而言,你需要了解: 1.正则表达式的基本了解 其实正则并不难,并且在学会后能带给你极

  • jQuery validate+artdialog+jquery form实现弹出表单思路详解

    功能描述: 在页面弹出一个form表单,ajax无刷新提交表单,表单需通过验证. 适用范围: 适用于在列表页面新增,修改记录. 需要加载的js文件: jquery.min.js artDialog.js iframeTools.js jquery.form.js jquery.validate.js 实现思路: 在页面中将表单放到一个隐藏的容器中,用artdialog弹出该form并对form加上jqueryvalidate验证,提交采用jqueryform ajax提交,由于都是用现成的插件写

  • 基于Bootstrap实现Material Design风格表单插件 附源码下载

    Jquery Material Form Plugin是一款基于Bootstrap的Material Design风格的jQuery表单插件.该表单通过自定义样式和jQuery来将Bootstrap的表单修改为扁平风格的表单,并带有浮动标签特效. 在线预览         源码下载 使用方法 使用该Material Design风格表单需要在页面中引入jquery,bootstrap相关文件和materialFormStyles.css.materialForm.js文件. <link rel=

  • vue中项目如何提交form格式数据的表单

    目录 vue提交form格式数据的表单 先将数据处理 数据上传 封装文件 vue form表单最简写法 vue提交form格式数据的表单 先将数据处理 let formData = new FormData(); for(let key in this.telForm){      formData.append(key,this.telForm[key]); } 数据上传 //采用封装的post方法上传 this.postRequest('web/login/mobile',formData)

  • jquery.form.js异步提交表单详解

    本文实例为大家分享了jquery.form.js异步提交表单的具体代码,供大家参考,具体内容如下 引入脚本: <script type="text/javascript" src="/js/jquery.form.min.js"></script> <script src="/js/json2.js"></script> //前端代码: <form id="f1">

  • 关于表单组件el-form中的prop的作用

    目录 表单组件el-form中prop的作用 el-form-item 设置prop报错 表单组件el-form中prop的作用 prop就是一个表单规则中的一个属性 如图: 表单规则和表单数据其实可以是相同的. el-form-item 设置prop报错 please transfer a valid prop path to form item! 官方解释: https://github.com/ElemeFE/element/issues/2327 但是真实的情况是: <template

  • Android实现Ant Design 自定义表单组件

    Ant Design 组件提供了Input,InputNumber,Radio,Select,uplod等表单组件,但实际开发中这是不能满足需求,同时我们希望可以继续使用Form提供的验证和提示等方法(使用起来确实很爽),这时需要自己动手封装一些表单,同时我们还要保持方法可以继续是使用. 组件的源码    https://github.com/haozhaohang/ant-design-expand-component 下面看一下如何自己封装表单组件,这是一个最基础的表单使用例子: impor

  • vue2实现封装动态表单组件

    目录 封装组件注意点 动态表单动态控制的是什么? 动态表单封装 风格一 风格二 (推荐优先采用此风格) 封装组件注意点 不要为了封装而封装 只封装不变的部分,将变化的部分通过slot或其他方式,暴露出去,交给调用者实现 为了提供封装组件的复用率,优先封装为UI组件,而不是封装为业务组件(即:封装组件内部使用到的数据,都通过prop获取,而不是直接通过ajax请求或vuex中获取) 动态表单动态控制的是什么? 已知的需要动态控制的场景: 在A界面显示:A, B, C三个表单项,B界面显示:A,B,

随机推荐