现在很多库,比如饿了么的element-ui的表单就是用的async-validate实现的表单校验,一般我们是这样的(以vue+element-ui为例)
template
<el -form :model="dataForm" ref="dataForm" :rules="dataFormRules">
</el><el -form-item label="名称" prop="name">
</el><el -input v-model="dataForm.name"></el>
<el -form-item label="版本" prop="version">
</el><el -input v-model="dataForm.version"></el>
javascript
dataFormRules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 1, max: 50, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
version: [
{ required: true, message: '请填写版本', trigger: 'blur' }
],
},
其中el-form-item的prop属性要跟dataFormRules里面的对应才行。
当时其实每个el-form-item也可以直接定义自己的rules属性
上面的校验是很常见的,效果也很不错
但是有时我们可能场景比这复杂的多
比如我们要动态添加表单,比如配置文件增删改查参数
原谅我刚才只放了上半部分
这种怎么校验?
我事先并不知道对应的是哪个键值对,顺带讲一下这种用vue怎么实现。首先双向绑定也很显然不可能用类似dataForm.xxx的方式了。后端返回的结果很可能是这样的
{
"code": 100,
"msg": null,
"data": {
"projectName": "动态注册",
"envName": "UAT",
"version": "文件",
"description": "文件描述",
"name": "上传文件",
"list": {
"client.param": "application",
"client.param2": "abcde"
}
}
}
这是我们只能自己处理下,当然主要是处理list
可以参考这样处理,把list变成这样的类似这样的结构
[
{keyName:"client.param",keyValue:"application"},
{keyName:"client.param2",keyValue:"abcde"}
]
这样我们就可以用v-for循环输出了
<el -form-item v-for="(item,index) in dataForm.keyValues" :key="index">
</el><el -col :span="3" slot="label">
</el><el -button
size="mini"
type="danger"
@click="handleDelete(item,index)">删除</el>
<el -col :span="4" justify="center">键名</el>
<el -col :span="8">
</el><el -input label="ok" size="small" v-model="item.keyName">
</el>
<el -col :span="4" justify="center">键值</el>
<el -col :span="8">
</el><el -input label="ok2" size="small" v-model="item.keyValue">
</el>
但是这样不够好,我们应该是一个el-input外面对应一个el-form-item
也就是应该用这种
<el -form-item label="描述" prop="description">
</el><el -input type="textarea" v-model="dataForm.description"></el>
<template v-for="(item,index) in dataForm.keyValues">
<el -button
size="mini"
type="danger"
:key="'btn' + index"
@click="handleDelete(item,index)">删除
</el>
<el -form-item v-for="(item2, index2) in item"
:rules="rules"
:prop="'keyValues.' + index + '.index2'"
:key="index + '-' + index2">
</el><el -input label="ok" size="small" v-model="item[index2]">
</el>
</template>
<el -form-item>
</el><el -button type="info" @click="handleAdd">新增参数</el>
const check = (rules,value,callback)=>{
console.log('value', value)
}
data(){
return{
rules:[{
validator: check, trigger:'blur'
}],
}
}
我们希望的是在input框移出的时候进行一些校验,就是上面的check函数,如果一切顺利的话,第二个参数value的值就应该是输入的值,然后我们就可以运用正则之类的进行处理了,但是上面的代码还是有点问题的,check方法里面输出的value是undefined,但是程序没有报错啊。
问题就出在
:prop="'keyValues.' + index + '.index2'"
我们先随意将其改成错误的,让程序报错,方便我调试定位
:prop="'keyValues' + index + '.index2fdfad'"
报错如下:Error in event handler for "el.form.blur": "Error: please transfer a valid prop path to form item!"
我们一步一步定位,定位到util.js?ca50:65上面
65行报的错,我们会发现path=keyValues0.index2fdfad并且path会两次正则替换,第一个是获取中括号[]里面的内容,第二个是将.替换掉。
实际上它的最终目的是要变成获取keyValues[0][index2]的值,简单说明下
keyValues = [
{keyName:"client.param",keyValue:"application"},
{keyName:"client.param2",keyValue:"abcde"}
]
index2 = keyName
index2 = keyValue
了解了套路我们就可以依次作为依据改props
:prop="'keyValues.' + index + '.' + index2"
现在我们就可以根据获取的值进行校验了
const check = (rules,value,callback)=>{
console.log('value', value)
if(!value === 'abc'){
callback('输入的不是abc');
}else{
callback();
}
}
8 条评论
普若木特 · 2018/05/17 20:47
@冰, 解决了问题就好
言西早小姐 · 2018/05/10 11:11
规格名有一个,规格值却有多个,我在这过程遇到的问题是规格名为空的时候会有校验提示,但是规格名不为空但规格值为空的情况下却没校验提示,这个问题我思考了好久还是没找到答案,希望大神指教下,谢谢哈
普若木特 · 2018/05/17 20:55
@言西早小姐, 大致明白你的意思,但是不确定,如果可以的话看下代码最好。
tonX · 2018/04/27 16:35
很棒棒的~解决了我的问题:)
想起了前刚用VUE的时候通过V-for实现动态生成组件,然后又苦恼无法对每个生成的组件进行管理,然后自己就给每个组件加上了个ID的方法…这里有异曲同工之妙呢.
普若木特 · 2018/04/27 23:00
@tonX, 这是我的荣幸
普若木特 · 2018/04/25 22:26
@冰, 主要自己要耐心打下断点就能发现它的规则,简单的说,对于能确定名字的就用字符串,对象变量(比如这里可能是keyName或者keyValue,并不确定)就直接用变量,用+拼接,但是需要注意的是如果两个都是变量时不能直接用+相加,已经用字符串param1 + ‘.’ + param2进行相加,这也是看到源码里面用到了.才知道的
冰 · 2018/05/18 13:33
@普若木特, 谢谢!
冰 · 2018/04/25 21:59
:prop这个地方还是不太好发现的,我之前做的项目也是自定义校验函数,但是不是报错,就是取不到值,学习了,搞定了我的问题,谢谢!