【发布时间】:2017-09-23 07:28:57
【问题描述】:
我有一个用例,我可能需要将对象props 作为道具传递给子组件。
最初,我在一个组件中包含一个表单和一个表格。此表单将接受输入,将执行异步请求并呈现表格以供用户进行选择。然后用户可以点击一个按钮并隐藏表格并恢复表单以便重新输入参数。由于表单的内容取决于其父级的状态,因此最后的搜索参数仍在表单中。
当我重构组件以使表单和表格成为父组件的子组件时,问题就出现了。现在表单会将$emit 事件传递给其父级,后者将执行异步操作并将结果作为props 传递给表。这工作得很好,但是当用户点击“返回表单”按钮时,表单被重新渲染,从而将其状态重置为初始值。
我尝试将表单的内容存储在父级中并将其作为props 传递回表单,但这导致了最初设置值的问题。我不想直接变异props,所以我尝试了这种方法:
FormContainer.vue
<template>
<div v-if="formShown">
<form-component :initialValues="formValues" @formSubmitted="displayResults"></form-component>
</div>
<div v-if="tableShown">
<table-component :results="fetchedResults" @returnToForm="returnToForm"></table-component>
</div>
</template>
<script>
export default {
data(){
return{
formShown: true,
tableShown: false,
formValues:{
address1: '',
address2: '',
address3: '',
country: ''
},
fetchedResults: []
}
},
methods:{
async displayResults(){
this.fetchedResults = await someAsynchronousCall();
this.formShown = false;
this.tableShown = true;
},
returnToForm(){
this.tableShown = false;
this.formShown = true;
}
}
}
</script>
FormComponent.vue
<template>
<!--Some form fields here, bound to data(){}, ommitted for brevity-->
</template>
<script>
export default{
props:['initialValues'],
data(){
return{
//Original structure
/*selectedAddress:{
address1: '',
address2: '',
address3: '',
country: ''
}*/
selectedAddress: JSON.parse(JSON.stringify(this.initialValues)) //Object.assign({}, this.initialValues) //tried both of these for deep copy
}
}
}
</script>
这样做的问题是,当组件最初创建时,它传递了一个空对象(或者更确切地说是一个只有空属性的对象,我认为它们相当于同一件事),这意味着我的数据属性正在获取初始化为undefined。
然后我尝试使用三元组来用 props 中的值或空字符串初始化数据对象,如下所示:
data(){
return{
selectedAddress: {
address1: this.initialValues.address1 ? this.initialValues.address1 :'',
address2: this.initialValues.address2 ? this.initialValues.address2 :'',
address3: this.initialValues.address3 ? this.initialValues.address3 :'',
country:this.initialValues.country ? this.initialValues.country :''
}
}
},
但这会引发错误,指出selectedAddress 未在实例上定义,但在渲染期间被引用。我猜这意味着使用三元来初始化道具是错误的。
然后我尝试检查 mounted(){} 生命周期钩子中的道具并在那里设置数据属性,如下所示:
mounted(){
if(!this.initialValues || _.isEmpty(this.initialValues)){
Logger.info(`no props passed, no setup needed`);
return;
}
if(this.initalValues.address1){
Logger.info(`setting address 1`);
this.selectedAddress.address1 = this.initalValues.address1;
}
if(this.initialValues.address2){
Logger.info(`setting address 2`);
this.selectedAddress.address2 = this.initalValues.address2;
}
if(this.initialValues.address3){
Logger.info(`setting address 3`);
this.selectedAddress.address3 = this.initalValues.address2;
}
if(this.initialValues.country){
Logger.info(`setting country`);
this.selectedAddress.country = this.initalValues.country;
}
}
这适用于表单的第一次运行,但在安装组件时this.initialValues 始终为undefined。我检查了组件状态,发现initialValues 确实存在,只是在mounted 生命周期挂钩期间不存在。无论如何,这种方法感觉很“hacky”。
我不确定从这里去哪里。如果重新安装表单,我可以将表单数据提交到商店并再次获取它,但我不觉得提交应该只在其父安装时才存在的东西是正确的方法。
谁能指导我采用更 Vue 的方式来实现这一目标?
【问题讨论】:
标签: javascript vuejs2 vue-component