[英]What's the best way to pass and retrieve data from a child form component?
This is my current method: 这是我目前的方法:
Parent.vue: Parent.vue:
// Template
<form-child :schema="schema"><form-child>
// JS
data () {
return {
schema: [{ // name: '', value: '', type: '' }, { //etc ... }]
}
}
FormChild.vue : 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
})
}
}
Is this the optimal way? 这是最佳方法吗? Or maybe there's a better one using
emit
and v-model
? 或者,也许有一个使用
emit
和v-model
的更好v-model
? (If so, could you provide a sample code?) (如果是这样,您能否提供示例代码?)
For what you are doing here, there is no need to separate the form into a component. 对于您在这里所做的事情,无需将表单分成一个组件。 Just make it part of the parent and use
v-model
. 只需使其成为父项的一部分并使用
v-model
。
new Vue({ el: '#app', data: { schema: [{ type: 'text', name: 'one', value: "1" }, { type: 'textarea', name: 'two', value: "stuff in the textarea" } ] } });
<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> <div v-for="field in schema"> <input v-if="field.type === 'text'" v-model="field.value"> <textarea v-if="field.type === 'textarea'" v-model="field.value"></textarea> </div> </div>
If you want the component for reusability and you don't care about insulating the parent from changes (best practice is not to have anything outside a component change its data), you can just wrap the same thing in a component: 如果您希望组件具有可重用性,并且您不关心使父级不受更改的影响(最佳实践是不要让组件外部的任何内容更改其数据),则可以将相同的内容包装在组件中:
new Vue({ el: '#app', data: { schema: [{ type: 'text', name: 'one', value: "1" }, { type: 'textarea', name: 'two', value: "stuff in the textarea" } ] }, components: { formChild: { props: ['value'] } } });
<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-child inline-template v-model="schema"> <div> <div v-for="field in value"> <input v-if="field.type === 'text'" v-model="field.value"> <textarea v-if="field.type === 'textarea'" v-model="field.value"></textarea> </div> </div> </form-child> </div>
A properly encapsulated child component would be decoupled from the parent data structure. 正确封装的子组件将与父数据结构分离。 It would take
type
and value
as separate props, plus an opaque id
to tell the parent which value the component is emitting about. 它会将
type
和value
作为单独的道具,外加一个不透明的id
来告诉父组件该组件所发出的值。
By making a settable computed based on the value
parameter, the component can use v-model
on its form elements. 通过基于
value
参数计算可设置value
,组件可以在其表单元素上使用v-model
。 The set
function emits an input
event with the id
and the newValue
, and the parent takes it from there. set
函数发出一个带有id
和newValue
的input
事件,父函数从那里接收它。
Update : I decided I didn't like the id
going to the component, so I handled that in the input handler: @input="updateField(index, $event)
. 更新 :我决定我不喜欢
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); } } } } } });
<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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.