刚刚开始接触Vue以及ElementUI,最近在开发过程中遇到了问题,经历了各种痛苦的debug....直接入正题把:
这里好像不可以传文件,我就直接贴代码了:
<template>
<div>
<el-button @click="onSelect">点我</el-button>
<el-dialog
title="弹窗"
:visible.sync="dialogVisible"
width="50%">
<el-form
ref="testForm"
:model="formData"
:rules="formRules">
<el-form-item label="类型">
<el-select v-model="formData.class">
<el-option label="类型1" value="class1"></el-option>
<el-option label="类型2" value="class2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="class1" v-if="formData.class=='class1'" prop="text">
<el-input type="textarea" v-model="formData.text"></el-input>
</el-form-item>
<el-form-item label="类型2" v-else prop="value">
<el-select v-model="formData.value" multiple>
<el-option label="sdf" value="11"></el-option>
<el-option label="dsaf" value="22"></el-option>
<el-option label="dyrt" value="33"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">ok</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
data(){
return {
dialogVisible: false,
formData: {
class: '',
text: '',
value: []
},
formRules: {
text: [{
required:true,
validator(rule, value, callback){
var Reg = /[\w+\/]*\w+/;
if(value==''){
callback(new Error('该字段不能为空'))
}else if(!value.match(Reg) || value.match(Reg)!=value){
callback(new Error('请输入正确的用户名,用户名之间用/隔开'));
}else{
callback();
}
}
}],
value: [{
required:true,
message:'不能为空'
}]
}
}
},
methods: {
onSubmit(){},
onSelect(){
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs.testForm.resetFields();
});
console.log(this.formData)
}
}
}
</script>
这个组件就是一个按钮,点击按钮会出现一个弹窗,图如下:
由于是提问题,尽量省去了无关代码,包括自定义组件以及css代码,所有的元素都由ElementUI提供。
问题重现步骤:
1.点开弹窗,选择类型为类型1,此时文本输入域会变为textarea,关闭弹窗。
2.再次点击按钮打开弹窗,控制台会报错,类型检测错误。
debug历程如下:
1.删掉el-form-item组件的prop属性,则不会报错。是表单数据对象检测错误。
2.去掉值表单验证也不会报错,证明数据对象检测在表单验证阶段出错。
3.确定自己定义的表单初始值类型并没有什么问题。
4.最后锁定问题出现在打开弹窗之后的重置表单方法resetFields
5.在resetFields方法之后输出表单数据,图如下
初始定义的表单数据如下
求各位大佬能给我解解惑,为啥我定义的text值为String,在经过表单之后会变为Array,究竟是我使用不规范还是ElementUI本身就认为textarea的字段值为Array亦或是其他问题,望指正。小弟在此拜谢各位大佬!
把
v-if/v-else
改成v-show
。https://jsfiddle.net/s5ar1un3...
我也才发现有这种坑,原理后面慢慢说。
以下为element-ui源码
form.vue
form-item.vue
从源码可以看出,在
form-item
的mounted
阶段确定每个field
的初始值。创建阶段
由于
v-if/v-else
,因此text
所在组件创建没有prop
(这时候创建了3个item
组件,class
本身也没写prop
情况会一样),因此只有value
所在item
组件创建的时候触发了form
组件的el.form.addField
事件。所以保存的fields
长度为1,仅保存了value
这个组件。选中之后
由于数据变动,
vue
比较差异更新,然后更新了第2个组件(这是重点)
,然鹅this.initialValue
是element-ui
定义的值,还是原来value
的值。结果就是
resetField
的时候value.initialValue
的值赋给了text
。结论所以resetField
千万别用v-if/v-show
除非你确认过上面的逻辑跟你的业务逻辑不冲突。测试版本element-ui@2.3.3
补充
以上都是不看文档的结果(花式打脸),
vue
提供了:key
阻止组件复用。Vuejs注意如
validate
组件不存在不验证一样,resetField
也不reset
。