iview ui 表单验证 深入了解
在开发xxx需求中,有个交互是动态添加问题项,并需要做表单验证,在做动态表单验证的过程中遇到了问题,记录下这次是如何解决的。
一直以来对ui框架的form表单验证只局限于 在form 加上 model、rules 、在form-item加上prop,而且要prop要与model、rules的值对应,例如:
<template>
<form model="questionformdata" :rules="questionrules" refs="questionformrefs">
<formitem prop="question" lable="问题描述">
<input v-model="questionformdata.question"></input>
</formitem>
</form>
</template>
<script>
export default {
data() {
return {
questionformdata: {
question: ''
},
questionrules: {
question: [{
{ required: true, message: "不允许为空", trigger: "blur" },
}]
}
}
},
methods: {
handlesubmit() {
this.$refs[name].validate(async valid => {
// valid true验证通过,false 验证不通过
});
}
}
}
</script>
这里要model="questionformdata"指向对应数据对象,:rules="questionrules"指对应规则,prop="question"指对应的表单项的要验证的key(即questionformdata.question);以前只知道这么写就能触发验证规则,但是具体的原理不太清楚。
这次需要动态添加表单项,就是循环渲染formitem,可问题来了,我要怎么去定义这个prop和rules,带着疑问,我查了一下iview官网,在form下找到对应例子
:prop="'items.' + index + '.value'"
:rules="{required: true, message: 'item ' + item.index +' can not be empty', trigger: 'blur'}"
原来可以动态添加prop 和rules,只要将prop指向对应的下标即可,重新调整了一下代码
<template>
<form model="questionformdata" :rules="questionrules" refs="questionformrefs">
<formitem
v-for="(item, index) of questionformdata.questions"
:prop="'questions.' + index +'.question'"
:rules="{required: true, message: '问题' + (index + 1) + '不允许为空', trigger: 'blur'}"
:lable="'问题' + (index + 1) +'描述"
>
<input v-model="questionformdata.question[index]"></input>
</formitem>
</form>
</template>
<script>
export default {
data() {
return {
questionformdata: {
questions: [{
id: 1,
question: '问题1'
}, {
id: 2,
question: '问题2'
}],
},
questionrules: {
}
}
}
}
</script>
经过上面的调整,动态表单的验证也生效了,这里需要注意,prop的值必须是questionformdata的key,即questions.[index].question,如上面的第一项的prop的值questions.0.question,如果换成items.0.question就不生效了。会报[iview warn]: please transfer a valid prop path to form item!,意思是说,prop的值在questionformdata中找不到。
动态表单的验证总算解决了,但是对questions.[index].question有些疑问,formitem是如何识别字符串,并与questionformdata的值关联起来的。带着问题看一下<formitem>源码。
探究原理
找到formitem源码,路径node_modules/view-design/src/components/form/form-item.vue,在源码中找到答案:
computed: {
fieldvalue () {
// forminstance 是当前form的实例,获取到model,也就是questionformdata
const model = this.forminstance.model;
if (!model || !this.prop) { return; }
// 此处的prop 就是 questions.0.question
let path = this.prop;
// 如果遇到:就替换为点,如questions:0.question -> questions.0.question
if (path.indexof(':') !== -1) {
path = path.replace(/:/, '.');
}
// 获取到questions.0.question在questionformdata的值
return getpropbypath(model, path).v;
},
},
function getpropbypath(obj, path) {
// tempobj = questionformdata
let tempobj = obj;
// 将中括号替换为. 如 questions[0][question] -> questions.0.question
path = path.replace(/\[(\w+)\]/g, '.$1');
// 替换首个., .questions.0.question -> questions.0.question 最终处理成这个格式
path = path.replace(/^\./, '');
// 分割成数组 得到 ['questions','0','question']
let keyarr = path.split('.');
let i = 0;
// 以 i = 0来查此处代码作用
for (let len = keyarr.length; i < len - 1; ++i) {
// key = questions
let key = keyarr[i];
// questions 在 questionformdata中,进入为true的代码块
if (key in tempobj) {
// tempobj = questions
tempobj = tempobj[key];
} else {
throw new error('[iview warn]: please transfer a valid prop path to form item!');
}
}
return {
o: tempobj, // { id: 1, question: '问题1' }
k: keyarr[i], // question
v: tempobj[keyarr[i]] // 问题1
};
}
原来是通过.去分割为数据,数组的值以key的形式去访问model对象,匹配上对应的值。当匹配不上值是会抛出'[iview warn]: please transfer a valid prop path to form item!'错误。
总结:通过阅读源码,我们可以发现动态添加校验规则不止可以用key.[index].key的方式,还可以通过[key][index][key]字符串的方式去定义prop,不过要注意**key要与model中的key一致**
以上就是iview ui form 动态添加表单项校验规则写法实例的详细内容,更多关于iview ui form 表单项校验规则的资料请关注代码网其它相关文章!
发表评论