剛剛開始接觸Vue以及ElementUI,最近在開發(fā)過程中遇到了問題,經(jīng)歷了各種痛苦的debug....直接入正題把:
這里好像不可以傳文件,我就直接貼代碼了:
<template>
<div>
<el-button @click="onSelect">點(diǎn)我</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('請(qǐng)輸入正確的用戶名,用戶名之間用/隔開'));
}else{
callback();
}
}
}],
value: [{
required:true,
message:'不能為空'
}]
}
}
},
methods: {
onSubmit(){},
onSelect(){
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs.testForm.resetFields();
});
console.log(this.formData)
}
}
}
</script>
這個(gè)組件就是一個(gè)按鈕,點(diǎn)擊按鈕會(huì)出現(xiàn)一個(gè)彈窗,圖如下:
由于是提問題,盡量省去了無關(guān)代碼,包括自定義組件以及css代碼,所有的元素都由ElementUI提供。
問題重現(xiàn)步驟:
1.點(diǎn)開彈窗,選擇類型為類型1,此時(shí)文本輸入域會(huì)變?yōu)閠extarea,關(guān)閉彈窗。
2.再次點(diǎn)擊按鈕打開彈窗,控制臺(tái)會(huì)報(bào)錯(cuò),類型檢測(cè)錯(cuò)誤。
debug歷程如下:
1.刪掉el-form-item組件的prop屬性,則不會(huì)報(bào)錯(cuò)。是表單數(shù)據(jù)對(duì)象檢測(cè)錯(cuò)誤。
2.去掉值表單驗(yàn)證也不會(huì)報(bào)錯(cuò),證明數(shù)據(jù)對(duì)象檢測(cè)在表單驗(yàn)證階段出錯(cuò)。
3.確定自己定義的表單初始值類型并沒有什么問題。
4.最后鎖定問題出現(xiàn)在打開彈窗之后的重置表單方法resetFields
5.在resetFields方法之后輸出表單數(shù)據(jù),圖如下
初始定義的表單數(shù)據(jù)如下
求各位大佬能給我解解惑,為啥我定義的text值為String,在經(jīng)過表單之后會(huì)變?yōu)锳rray,究竟是我使用不規(guī)范還是ElementUI本身就認(rèn)為textarea的字段值為Array亦或是其他問題,望指正。小弟在此拜謝各位大佬!
把v-if/v-else
改成v-show
。
https://jsfiddle.net/s5ar1un3...
我也才發(fā)現(xiàn)有這種坑,原理后面慢慢說。
form.vue
//created階段
created() {
this.$on('el.form.addField', (field) => {
if (field) {
this.fields.push(field);
}
}
this.$on('el.form.removeField', (field) => {
if (field.prop) {
this.fields.splice(this.fields.indexOf(field), 1);
}
});
}
//重置方法
resetFields() {
...
this.fields.forEach(field => {
field.resetField();
});
},
form-item.vue
//mounted階段
mounted() {
if (this.prop) {
this.dispatch('ElForm', 'el.form.addField', [this]);
...
let initialValue = this.fieldValue;
...
Object.defineProperty(this, 'initialValue', {
value: initialValue
});
...
}
}
//重置方法
resetField() {
this.validateDisabled = true;
if (Array.isArray(value)) {
prop.o[prop.k] = [].concat(this.initialValue);
} else {
prop.o[prop.k] = this.initialValue;
}
}
從源碼可以看出,在form-item
的mounted
階段確定每個(gè)field
的初始值。
創(chuàng)建階段
由于v-if/v-else
,因此text
所在組件創(chuàng)建沒有prop
(這時(shí)候創(chuàng)建了3個(gè)item
組件,class
本身也沒寫prop
情況會(huì)一樣),因此只有value
所在item
組件創(chuàng)建的時(shí)候觸發(fā)了form
組件的el.form.addField
事件。所以保存的fields
長(zhǎng)度為1,僅保存了value
這個(gè)組件。
選中之后
由于數(shù)據(jù)變動(dòng),vue
比較差異更新,然后更新了第2個(gè)組件(這是重點(diǎn))
,然鵝this.initialValue
是element-ui
定義的值,還是原來value
的值。
結(jié)果就是resetField
的時(shí)候value.initialValue
的值賦給了text
。
所以resetField
千萬別用v-if/v-show
除非你確認(rèn)過上面的邏輯跟你的業(yè)務(wù)邏輯不沖突。測(cè)試版本element-ui@2.3.3
以上都是不看文檔的結(jié)果(花式打臉),vue
提供了:key
阻止組件復(fù)用。Vuejs
Vue 會(huì)盡可能高效地渲染元素,通常會(huì)復(fù)用已有元素而不是從頭開始渲染。這么做除了使 Vue 變得非??熘猓€有其它一些好處。例如,如果你允許用戶在不同的登錄方式之間切換這樣也不總是符合實(shí)際需求,所以 Vue 為你提供了一種方式來表達(dá)“這兩個(gè)元素是完全獨(dú)立的,不要復(fù)用它們”。只需添加一個(gè)具有唯一值的 key 屬性即可:
注意如validate
組件不存在不驗(yàn)證一樣,resetField
也不reset
。
被題主坑死,不按你debug歷程,這問題早解決了。。話不多說,上代碼:
<template>
<div>
<el-button @click="onSelect">點(diǎn)我</el-button>
<el-dialog
title="彈窗"
:visible.sync="dialogVisible"
width="50%">
<el-form
ref="formData"
:model="formData"
:rules="formRules">
<el-form-item label="類型">
<el-select v-model="formData.Type">
<el-option label="類型1" value="class1"></el-option>
<el-option label="類型2" value="class2"></el-option>
</el-select>
</el-form-item>
<div v-if="formData.Type=='class1'">
<el-form-item label="class1" prop="desc">
<el-input type="textarea" v-model="formData.desc"></el-input>
</el-form-item>
</div>
<div v-else>
<el-form-item label="類型2" prop="region">
<el-select v-model="formData.region" 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>
</div>
<el-form-item>
<el-button type="primary" @click="onSubmit('formData')">ok</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
data(){
return {
dialogVisible: false,
formData: {
Type: 'class1',
desc: '',
region: []
},
formRules: {
desc: [
{
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('請(qǐng)輸入正確的用戶名,用戶名之間用/隔開'));
}else{
callback();
}
}
}
],
region: [
{ required:true, message:'不能為空', trigger: 'change' }
]
}
}
},
methods: {
onSubmit(formName){
this.$refs[formName].validate((valid) => {
if (valid) {
this.dialogVisible = false;
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
onSelect(){
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs.formData.resetFields();
console.log(this.Type)
});
console.log(this.formData)
}
}
}
</script>
你的問題就是v-if/v-else這里,因?yàn)槟愠跏糡ype為' ',v-if="formData.Type=='class1'",所以你才顯示的是textarea這塊。但是你第二次點(diǎn)擊,執(zhí)行resetFields后,Type為undefined,顯示卻為select這塊,desc的類型會(huì)因?yàn)橹刂米兊母鷕egion一樣,為Array;這也解釋了為什么你第一次選擇類型2,第二次點(diǎn)擊進(jìn)來,不會(huì)報(bào)錯(cuò)。
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
北大青鳥中博軟件學(xué)院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學(xué)院和江蘇省首批服務(wù)外包人才培訓(xùn)基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團(tuán)創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機(jī)構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團(tuán),成為集合面授教學(xué)培訓(xùn)、網(wǎng)
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問,美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。