【elementUi】关于el-form使用自定义校验规则的传参问题
需求:在很多时候,我们的form表单并不是一个个写出来的,而是通过数据遍历渲染的,所以绑定的prop值 model值 rule值等等都不是常规的写法
1.常规
常规的写法:
绑定的数据格式:
但是现在,有很多输入表单,我们不会一个一个去写,而是通过数据了渲染(正应了VUE数据驱动试图?)
2.需要的效果:
由于布局高度相似,所以我们可以考虑循环。
先构思数据应该是什么样的,每一个el-form-item会包含它的绑定值v-model,规则rules,placeholder,甚至还有clearable disabled等属性
然后通过数据去构建视图
今天的重点是校验规则。由于写法不同平常,所以为每个form-item单独配置校验规则 :rules="item.rules"
有余自定义的校验规则可以放在当前的vue文件中
比如:
然后在规则中直接引用
但是这样校验规则接没有办法复用,我们可以把所有的校验规则提取成公共的JS文件,export出去,在需要用的vue文件中import进来,在对应的rules上像上边一样使用
这样最大程度的解耦可以服用,但也出现问题,比如本文中的需求,所绑定的v-model的值是children里的nodel 自定义规则的参数value并不能读取到该值
所以我这里想到通过bind传递this,
这里为什么写的这么麻烦?我的初衷是通过bind绑定到this,第二个参数直接传递所需要的数据,但是不知道为什么,传this可以读取到,读取再深一点this.boxData或者更深就读不到了
其实在this上年是可以看到具体属性的。知道的还请不吝赐教
所以这里我就这么传参数了 validPercent.bind(this, this, 0, 0)
第一个参数this: 绑定到this
第二个参数this:传递的数据
第三个参数0:该数据所处于boxData的第一层级的index
第四个参数0:该数据所处于boxData的第二层级的index
这两个参数都是为了方便在校验规则里取到对应的value值,这样就达到了传参的目的,思路是这样,但由于上边说的问题,应该还可以精简
插曲: 单个可以执行校验,点击确定按钮的时候无法校验,没有错误提示
有警告
只要随便绑定一个model就可以了
3.代码:
<template> <div class="outerDiv"> <div class="content"> <div class="form"> <el-form ref="form" :model="form"> <div v-for="(itemSum, idxSum) in boxData" :key="idxSum"> <el-divider>{{itemSum.txt}}</el-divider> <el-row> <el-col v-for="(item, idx) in itemSum.children" :key="idx" :span="8"> <el-form-item v-if="item.type==='select'" :label="item.label" :prop="item.prop" :rules="item.rules"> <el-select v-model="item.model" :placeholder="item.placeholder" size="medium" :disabled="item.disabled" clearable> <el-option v-for="val in item.options" :key="val.code" :label="val.name" :value="val.code"> </el-option> </el-select> </el-form-item> <el-form-item v-if="item.type==='input'" :label="item.label" :prop="item.prop" :rules="item.rules"> <el-input v-model.trim="item.model" size="medium" :placeholder="item.placeholder" clearable :disabled="item.disabled" clearable></el-input> </el-form-item> </el-col> </el-row> </div> </el-form> <div style="text-align: right"> <el-button class="btnnormal marginR" type="primary" disabled>修改</el-button> <el-button class="btnnormal" type="primary" @click="submitEvent">执行</el-button> </div> </div> </div> </div> </template>
<script> import { validPercent } from '@/validator/validator' export default { name: 'ALarm', data() { return { form: { }, boxData: [{ txt: '盯盘维度', children: [{ type: 'select', model: '', prop: 'user_name', label: 'PIN', placeholder: '请选择PIN', options: [{ name: '小米', code: '小米' }], rules: { required: true, validator: validPercent.bind(this, this, 0, 0), trigger: 'change' }, disabled: false }, { type: 'input', model: '', prop: 'user_password', label: '密码', placeholder: '请输入密码', rules: { required: true, validator: validPercent.bind(this, this, 0, 1), trigger: 'blur' }, disabled: true }, ] }, { txt: '触发条件', children: [{ type: 'select', model: '', prop: 'data', label: '时间', placeholder: '请选择时间', rules: { required: true, validator: validPercent.bind(this, this, 1, 0), trigger: 'change' }, options: [], disabled: true }, ] }, { txt: '执行操作', children: [{ type: 'select', model: '1', prop: 'optionType', label: '操作类型', placeholder: '请选择操作类型', rules: { required: true, validator: validPercent.bind(this, this, 2, 0), trigger: 'change' }, options: [{ name: '企业微信发送通知', code: '1' }], disabled: false }, { type: 'input', model: '', prop: 'qywx_id', label: '企业微信ID', placeholder: '请输入企业微信ID', rules: { required: true, validator: validPercent.bind(this, this, 2, 1), trigger: 'blur' }, disabled: false }, ] }, ] } }, methods: { submitEvent() { const vm = this; let data = {}
// 每个表单绑定的是对应数据中的model,字段名就是prop,这样处理一下要提交的数据 for (let i of vm.boxData) { for (let j of i.children) { vm.$set(data, j.prop, j.model) } } vm.$refs.form.validate((valid) => { if (valid) { // 执行对应的接口操作 } }) } } } </script>
export const validPercent = (zhi, outerIdx, innerIdx, rule, value, callback) => { let iptVale = zhi.boxData[outerIdx].children[innerIdx].model let iptPlaceHolder = zhi.boxData[outerIdx].children[innerIdx].placeholder if(iptVale) { return callback() } else { return callback(new Error(iptPlaceHolder)) } }