如何将父级到子级动态数据传递到具有多个字段的模型中 - Vue?

问题描述

我正在使用 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 机制为基础,但如果您愿意,它可以潜在地使您的模板更简洁。

默认情况下,Vue 中的

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 存储在父级中的值。