这是我目前的方法:
Parent.vue:
// Template
<form-child :schema="schema"><form-child>
// JS
data () {
return {
schema: [{ // name: '', value: '', type: '' }, { //etc ... }]
}
}
FormChild.vue :
// Template
<div v-for="field in schema">
<input v-if="field.type === 'text'" @change="updateValue(field.name, field.value)">
<textarea v-if="field.type === 'textarea'" @change="updateValue(field.name, field.value)">/textarea>
</div>
// JS
props: {
schema: Arrary
}
methods: {
updateValue (fieldName, fieldValue) {
this.schema.forEach(field => {
// this makes schema update in Parent.vue
if (field.name === fieldName) field.value = fieldValue
})
}
}
这是最佳方式吗?或者使用emit
和v-model
可能会更好? (如果是,您能提供示例代码吗?)
答案 0 :(得分:1)
正确封装的子组件将与父数据结构分离。它需要type
和value
作为单独的道具,加上一个不透明的id
来告诉父母组件发出的值。
通过基于value
参数计算可设置,组件可以在其表单元素上使用v-model
。 set
函数会使用input
和id
发出newValue
个事件,并且父级会从那里获取该事件。
更新:我觉得我不喜欢id
去组件,所以我在输入处理程序中处理了这个问题:@input="updateField(index, $event)
。
new Vue({
el: '#app',
data: {
schema: [{
type: 'text',
name: 'one',
value: "1"
},
{
type: 'textarea',
name: 'two',
value: "stuff in the textarea"
}
]
},
methods: {
updateField(index, newValue) {
this.schema[index].value = newValue;
}
},
components: {
formInput: {
props: ['type', 'value'],
computed: {
proxyValue: {
get() { return this.value; },
set(newValue) {
this.$emit('input', newValue);
}
}
}
}
}
});
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
<div v-for="field in schema">
{{field.name}} = {{field.value}}
</div>
<form-input inline-template v-for="field, index in schema" :type="field.type" :key="index" :value="field.value" @input="updateField(index, $event)">
<div>
<input v-if="type === 'text'" v-model="proxyValue">
<textarea v-if="type === 'textarea'" v-model="proxyValue"></textarea>
</div>
</form-input>
</div>
&#13;