弹窗表单

基于 vue + element-ui 的弹窗表单最佳实践

数据回显

数据回显主要分为两种情况,一种是通过在弹窗组件里面去调用详情接口回显数据,一种是从父组件中传值回显。

  1. 调用接口获取详情回显数据—在组件调用的地方给一个判断,避免在父组件初始化时就调用弹窗里的详情接口。
  2. props 父组件向子组件传值
<!-- 父组件调用 dialogTest 组件 -->
<dialog-test
    v-if="dialogStatus"
    :dialog-status="dialogStatus"
    :dialog-title="dialogTitle"
    :handle-type="handleType"
    @close-dialog="dialogStatus=false">
</dialog-test>
  1. 用 ref 从父组件操作子组件方法
  • 注:通过ref 传值,由于传的值是在方法里拿到的,而不是在子组件初始化时拿到的数据,所以在用 resetFields 重置表单时,通过ref传过来的值会被重置清空调
<!-- 父组件 -->
<dialog-test
    ref="dialog"
    v-if="dialogStatus"
    :dialog-status="dialogStatus"
    :dialog-title="dialogTitle"
    :handle-type="handleType"
    @close-dialog="dialogStatus=false">
</dialog-test>

<script>
    export default {
        data() {},
        methods: {
            edit(row) {
                this.dialogStatus = true
                this.dialogTitle = '修改'
                this.handleType = 'edit'
                // ref 和 v-if 渲染问题,用this.$nextTick来进行判断当前是否数据和dom已经加载完成了,加载完成了,再执行打开弹窗操作
                this.$nextTick(() => {
                    // 子组价直接在 open() 方法里获取 row里的数据
                    this.$refs.dialog.open(row)
                })
            }
        }
    }
</script>
<!-- 子组件 -->
<script>
    export default {
        data() {
            return {
                form: {}
            }
        },
        methods: {
            open(row) {
                Object.keys(this.form).forEach(key => {
                    this.form[key] = row[key]
                })
            }
        }
    }
</script>

表单重置

  • resetFields:对该表单项进行重置,将其值重置为初始值并移除校验结果
  • 注意点: resetFields 只能重置用prop绑定的字段,没有prop绑定的字段需要手动重置
<script>
    export default {
        methods: {
            reset() {
                 this.$refs.form.resetFields()
                 // resetFields 只能重置绑定有 prop 的字段,未被绑定的需手动重置
                 this.form.start = ''
                 this.form.end = ''
             },
        }
    }
 </script>

表单校验

实现表单校验的主要属性:

属性类型备注
ref-给元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs 对象上
rulesObject表单检验规则
modelObject表单数据对象
propString表单域model字段,在使用 validate、resetFields 方法的情况下,该属性必填

表单方法:

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

表单校验:

<el-form :model="form" ref="formRef" :rules="rules" label-width="100px" size="small">
    <el-form-item label="活动名称" prop="name">
        <el-input class="dialog-input" v-model="form.name" :maxlength="55" placeholder="请输入活动名称"></el-input>
    </el-form-item>
</el-form>
<el-button type="primary" size="small" @click="submit">确 定</el-button>
<script>
    export default {
        data() {
            let nameCheck = (rule, value, callback) => {
                const reg = /^[a-z]+([-]?[a-z0-9])*$/
                if(!value) {
                    callback(new Error('活动名称不能为空'))
                } else if(!reg.test(value)) {
                    callback(new Error('只能包含小写字母、数字及分隔符('-'),且必须以小写字母开头,数字或小写字母结尾'))
                } else {
                    callback()
                }
            }
            return {
                form: {
                    name: ''
                },
                rules: [
                    name: [
                        { required: true, message: '请输入活动名称', trigger: 'blur' },
                        { validator: nameCheck, trigger: 'blur' }
                    ]
                ]
            }
        },
        methods: {
            submit() {
                this.$refs.formRef.validate((valid) => {
                    if(valid) {
                        // 校验通过,执行提交操作
                        // dosomething……
                    }
                })
            }
        }
    }
</script>

在表单校验过程中,可能存在一个文本标签对应着多个填选框,以以下两种场景为例:

  1. 针对每一个输入框做校验提示(各输入框的错误提示显示在相应输入框的下方)
<el-form :model="form" ref="formRef" :rules="rules" label-width="100px" size="small">
      <el-form-item label="环境变量" required>
          <el-row>
              <el-col :span="8">
                  <el-form-item prop="envName">
                      <el-input class="dialog-input" v-model="form.envName" :maxlength="50"></el-input>
                  </el-form-item>
              </el-col>
              <el-col :span="1">
                  <span> = </span>
              </el-col>
              <el-col :span="8">
                  <el-form-item prop="envNum">
                      <el-input class="dialog-input" v-model="form.envNum" :maxlength="50"></el-input>
                  </el-form-item>
              </el-col>
          </el-row>
      </el-form-item>
  </el-form>
  <script>
      export default {
          data() {
              return {
                  form: {
                      envName: '',
                      envNum: ''
                  },
                  rules: {
                      envName: [
                          { required: true, message: '请输入变量名', trigger: 'blur' }
                      ],
                      envNum: [
                          { required: true, message: '请输入变量值', trigger: 'blur' }
                      ]
                  }
              }
          }
      }
  </script>
  1. 用一个 prop 对多个输入框做校验(多个输入框的校验提示显示在同一个位置)
<el-form :model="form" ref="formRef" :rules="rules" label-width="100px" size="small">
   <!-- 两个或多个输入框用一个提示 -->
   <el-form-item label="阈值范围" prop="ratio">
       <el-input class="ratio-input" v-model="form.start" :maxlength="2"></el-input>
       <span> - </span>
       <el-input class="ratio-input" v-model="form.end" :maxlength="2"></el-input>
   </el-form-item>
</el-form>
<script>
   export default {
       data() {
            let ratioCheck =(rule, val, callback) => {
                // 给 ratio 一个初始值,才能跳到该方法里对 start end 输入框的值做校验
               if(!this.form.start && !this.form.end) {
                   callback(new Error('请输入阈值范围'))
               } else if(this.form.start && !this.form.end) {
                   callback(new Error('请输入最大值'))
               } else if(!this.form.start && this.form.end) {
                   callback(new Error('请输入最小值'))
               } else {
                   callback()
               }
           }
           return {
               form: {
                   ratio: '121', 
                   satrt: '',
                   end: ''
               },
               rules: {
                   ratio: [
                       { required: true, message: '请输入阈值范围', trigger: 'blur' },
                       { validator: ratioCheck, trigger: 'blur' }
                   ],
               }
           }
       }
   }
<script>

防重复点击

  1. 给定一个变量,每次点击过后给按钮loading置为true,等所有的操作结束后再将按钮 loading状态置为 false。
<el-button type="primary" size="small" @click="submit" :loading="btnLoading">确 定</el-button>
<script>
    export default {
        data() {
            return {
                btnLoading: false
            }
        },
        methods: {
            submit() {
                this.btnLoading = true
                    setTimeout(() => {
                        this.btnLoading = false
                        this.cancel()
                    },1000)
            }
        }
    }
</script>
Logo

前往低代码交流专区

更多推荐