# 表单模版

# 详情

# :form-attr 表单属性

  formAttr: { title: '用户管理', size: 'small' }

# :item-attr 项属性

itemAttr: [
  { label: '工号:', type: 'input', key: 'no', maxlength: 30 },
  { label: '姓名:', type: 'input', key: 'name', maxlength: 50 },
  { label: '手机号:', type: 'input', key: 'phone', maxlength: 50 },
  { label: '邮箱:', type: 'input', key: 'email', maxlength: 50 },
  { label: '用户类型:', type: 'select', key: 'userType' },
  { label: '账号状态:', type: 'radio', key: 'status' },
  {
    label: '业务警种:',
    type: 'checkbox',
    key: 'policeCategory',
    width: '98%',
    multiple: true
  },
  { label: '入职日期:', type: 'daterange', key: 'inDate' },
  { label: '在职状态:', type: 'radio', key: 'jobStatus' },
  { label: '离职日期:', type: 'daterange', key: 'outDate', disabled: true }
]

# :rules 表单校验属性

自定义校验:

  • 手机号、邮箱 等
    • 1.先声明一个匿名函数
    • 2.把函数名赋值给 validator 即可
const checkPhone = (rule, value, callback) => {
  if (value === '') {
    callback(new Error('请输入手机号'))
  } else if (!regPhone.test(value)) {
    callback(new Error('手机格式错误'))
  } else {
    callback()
  }
}
  rules: {
    no: [{ required: true, message: '请输入工号', trigger: 'blur' }],
    name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
    phone: [{ required: true, trigger: 'blur', validator: checkPhone }],
    email: [{ trigger: 'blur', validator: checkEmail }],
    userType: [{ required: true, message: '请选择用户类型', trigger: 'blur' }],
    jobStatus: [{ required: true, message: '请选择在职状态', trigger: 'blur' }],
    inDate: [{ required: true, message: '请选择入职日期', trigger: 'blur' }],
    policeCategory: [{ required: true, message: '请选择业务警种', trigger: 'blur' }],
    status: [{ required: true, message: '请选择账号是否启用', trigger: 'blur' }]
  }

提示:

多选类型 types 和默认值 def-value 可以动态获取

# :types 多选赋值属性

  types: {
    userType: [
      { value: '01', label: '普通客服' }, 
      { value: '02', label: '部门负责人' }, 
      { value: '03', label: '管理员' }
    ],
    policeCategory: [
      { value: '01', label: '交管' },
      { value: '02', label: '户政(治安)' },
      { value: '03', label: '出入境' },
      { value: '04', label: '监所' },
      { value: '05', label: '技防' },
      { value: '06', label: '法制' }
    ],
    status: [{ value: '01', label: '启用' }, { value: '02', label: '停用' }],
    jobStatus: [{ value: '01', label: '在职' }, { value: '02', label: '离职' }]
  }

# :def-value 默认值属性

  defValue: { status: '01', jobStatus: '01' }

提示:

formCompEl 是表单的锚点 ref="formCompEl"

# submitForm() 提交方法

/** return Promise() */
this.$refs['formCompEl']
  .submitForm()
  .then(formData => {
    console.log(formData)
  })

# resetForm() 重置表单方法

this.$refs['formCompEl'].resetForm()

# @change(formData) 多选手动改变值事件

# 交互按钮

提示:

表单最后提供了一个 slot

    <MyForm 
      ref="formCompEl" 
      :form-attr="formAttr" 
      :item-attr="itemAttr" 
      :rules="rules" 
      :types="types" 
      :def-value="defValue"
      @change="onchange">
        <el-form-item>
          <el-button type="primary" @click="submitForm">保存</el-button> 
          <el-button type="info" @click="resetForm">重置</el-button>
        </el-form-item>
    </MyForm>

# 组件源码

<template>
  <div class="form-components">
    <div v-if="formAttr.title" style="display: flex;">
      <el-divider 
        content-position="left" 
        class="title"
      >
        {{ formAttr.title }}
      </el-divider>
    </div>
    <el-form
      ref="formEl"
      :rules="rules"
      :model="form"
      :size="formAttr.size ? formAttr.size : 'small'"
      :label-width="formAttr.lableWidth ? formAttr.lableWidth : '150px'"
    >
      <template v-for="(item, index) in itemAttr">
        <div 
          :key="index" 
          class="box-item" 
          :style="'width:' + (item.width ? item.width : '49%')"
        >
          <el-form-item :prop="item.key" :label="item.label">
            <!-- 输入框 -->
            <div v-if="item.type === 'input'" :style="'width:' + item.inputWidth">
              <el-input
                v-model="form[item.key]"
                clearable
                :disabled="item.disabled"
                :maxlength="item.maxlength"
                :placeholder="item.placeholder"
              />
            </div>
            <!-- 多行文本框 -->
            <div 
              v-else-if="item.type === 'textarea'" 
              :style="'width:' + item.inputWidth"
            >
              <el-input
                v-model="form[item.key]"
                type="textarea"
                clearable
                :rows="item.rows"
                :maxlength="item.maxlength"
                :placeholder="item.placeholder"
              />
            </div>
            <!-- 单选框 -->
            <div 
              v-else-if="item.type === 'radio'" 
              :style="'width:' + item.inputWidth"
            >
              <el-radio-group 
                v-if="types[item.key]" 
                v-model="form[item.key]" 
                @change="onchange"
              >
                <el-radio
                  v-for="(type, indexRadio) in types[item.key]"
                  :key="indexRadio"
                  :label="type.value"
                >{{ type.label }}</el-radio>
              </el-radio-group>
            </div>
            <!-- 复选框 -->
            <div 
             v-else-if="item.type === 'checkbox'" 
             :style="'width:' + item.inputWidth"
            >
              <el-checkbox-group v-if="types[item.key]" v-model="form[item.key]">
                <el-checkbox
                  v-for="(type, indexCbox) in types[item.key]"
                  :key="indexCbox"
                  :label="type.value"
                >{{ type.label }}</el-checkbox>
              </el-checkbox-group>
            </div>
            <!-- 下拉框 -->
            <div 
             v-else-if="item.type === 'select'" 
             :style="'width:' + item.inputWidth"
            >
              <el-select
                v-model="form[item.key]"
                :multiple="item.multiple"
                :placeholder="item.placeholder"
                clearable
                style="width: 100%;"
              >
                <el-option
                  v-for="(select, selectKey) in types[item.key]"
                  :key="selectKey"
                  :label="select.label"
                  :value="select.value"
                />
              </el-select>
            </div>
            <!-- 日期选择 -->
            <div v-else :style="'width:' + item.inputWidth">
              <el-date-picker
                v-model="form[item.key]"
                :type="item.type"
                :placeholder="item.placeholder"
                :disabled="item.disabled"
                range-separator="-"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                clearable
                style="width: 100%;"
                :value-format="(item.valueFormat ? item.valueFormat : 'timestamp')"
              />
            </div>
          </el-form-item>
        </div>
      </template>
      <slot />
    </el-form>
  </div>
</template>
<script>
export default {
  name: 'FormTempComponents',
  props: {
    formAttr: { type: Object, default: ()=> { title: '' } },
    itemAttr: { type: Array,  default: ()=> [] },
    rules: { type: Object, default: ()=> {} },
    types: {  type: Object, default: ()=> {} },
    defValue: { type: Object, default: ()=> {} }
  },
  data() {
    return { 
      form: {}
    }
  },
  watch: {
    defValue(v) {
      Object.keys(v).forEach(key => {
        this.$set(this.form, key, v[key])
      })
    }
  },
  created() {
    this.itemAttr.forEach(elem => {
      if (elem.type === 'checkbox') {
        this.$set(this.form, elem.key, [])
      }
    })
  },
  mounted() {
    if (JSON.stringify(this.defValue) !== '{}') {
      Object.keys(this.defValue).forEach(key => {
        this.$set(this.form, key, this.defValue[key])
      })
    }
  },
  methods: {
    onchange() {
      const newObj = JSON.parse(JSON.stringify(this.form))
      this.$emit('change', newObj)
    },
    submitForm() {
      const newFormObj = JSON.parse(JSON.stringify(this.form))
      const isValidate = JSON.stringify(this.rules)

      return new Promise((resolve, reject) => {
        if (isValidate !== '{}') {
          this.$refs['formEl'].validate((valid) => {
            if (valid) {
              resolve(newFormObj)
            } else {
              reject()
            }
          })
        } else {
          resolve(newFormObj)
        }
      })
    },
    resetForm() {
      // TODO
      Object.keys(this.form).forEach(key => {
        this.$set(this.form, key, null)
      })
      this.$emit('onreset')
    }
  }
}
</script>
<style scoped>
.form-components >>> .el-divider__text {
  font-size: 18px;
}
.form-components .box-item {
  display: inline-block;
}
</style>

上次更新时间: 2019-11-29 5:44:11 PM