问题描述
我正在使用 Vue 2 并且我试图让父组件将多个值传递给子组件,并让子组件将特定对象返回给父组件。需要对数据进行双向数据绑定。
例如我有这个学校对象:
school: {
name: "Tech School",type: "highschool"
}
data () {
return {
totalStudents: [{
school: {
name: "Tech School",type: "highschool"
},studentId: 123,city: "seattle"
},school: {
name: "Art School",type: "university"
}
studentId: 747,city: "toronto"
},}],}
}
<CustomChildPicker :value="prop" @input="prop=
totalStudents[index].school,// trying to pass these 3 fields from parent to child
totalStudents[index].studentId,totalStudents[index].city"
v-model=totalStudents[index].school //only want this updated data back from child
/>
我们如何将动态数据传递给子组件,但只有学校对象与父组件有两种方式的数据绑定?
我想将数据从父级传递给子级,子级对该数据进行一些转换并将转换后的数据传递回父级。 (学校对象)
但如果父级中的数据发生变化,子级会获取更新后的更改数据,重做上面的转换并将更新后的数据返回给父级。 (如果学生所在的城市发生变化,那么他们的学校也会发生变化)
我们将如何做到这一点?感谢您的帮助!
解决方法
在 Vue 中有一个“口头禅”:“道具下降,事件上升”。
这意味着你必须通过使用 v-bind
-> props
(parent -> child) & $emit
-> {{1} 来创建双向绑定的“循环” }}(孩子 -> 父母)
v-on
Vue.component('ChildComponent',{
// receiving data from parent v-bind
props: ['this','going'],computed: {
// this is the reactive data we use in the child
propsToParent: {
get() {
return {
this: this.this,going: this.going
}
},set(val) {
this.$emit("update:parent-data",val)
}
}
},data() {
return {
// only for the snippet (toggle)
toggleUp: true,}
},methods: {
// here you can do calculations in the child component
emitData() {
this.propsToParent = {
...this.propsToParent,going: this.toggleUp ? 'up' : 'down'
}
// only for the snippet (toggle)
this.toggleUp = !this.toggleUp
}
},template: `
<div>
PROPS FROM PARENT: {{ propsToParent }}<br />
<button
@click="emitData"
>
SEND TO PARENT
</button>
</div>
`
})
new Vue({
el: "#app",data() {
return {
dataDown: {
this: "is",going: "down",},methods: {
updateDataDown(val) {
this.dataDown = { ...this.dataDown,...val
}
}
},template: `
<div>
PARENT DOWN: {{ dataDown }}
<hr>
<ChildComponent
v-bind="dataDown"
v-on:update:parent-data="(val) => updateDataDown(val)"
/>
</div>
`
})
手动道具/事件方式已经展示,所以我将添加如何设置和使用自定义v-model
。它以完全相同的 props-down-events-up 机制为基础,但如果您愿意,它可以潜在地使您的模板更简洁。
v-model
设置为使用 value
属性作为输入,使用 input
事件作为输出。但是我们可以将这些更改为我们想要的任何内容using Vue's model
option:
model: {
prop: 'school',event: 'click'
},
因此,在您的情况下,由于您希望 school
成为 v-model
值,因此我们可以像这样设置组件的内部结构,为要传递给的每个值配置一个 prop子,并在 v-model
选项中配置您希望 model
使用的道具和事件:
default export {
name: "CustomChildPicker",// Specify props you want your component to accept:
props: {
school: Object,studentId: Number,city: String,// Specify which prop and event Vue should use for v-model:
model: {
prop: 'school',event: 'schoolUpdate' // Can be anything,custom or otherwise
},// Other options as needed:
data() { return {. . .}; },methods: {. . .},computed: {. . .},watch: {. . .},// Etc.
}
然后您可以在这样的模板中使用它:
<CustomChildPicker v-model="totalStudents[index].school"
:studentId="totalStudents[index].studentId"
:city="totalStudents[index].city"
/>
重要说明:您需要在子组件的某处包含对 $emit()
的调用,以手动发出触发 v-model
更新的事件。只需确保正确连接事件的值,以便它实际发出新的 school
值:
this.$emit('schoolUpdate',*new_school_value*);
在此示例中,*new_school_value*
只是您的实际更新学校值的替代,您需要手动将其提供为 $emit()
第二个论点。
您可以将此调用放在组件中任何有意义的地方,但是 $emit()
需要 的第二个参数是学校的更新值,无论您在使用中看起来如何,因为这是将通过 v-model
存储在父级中的值。