Как использовать контролируемые компоненты в Vue для установки значений в объекте родительского компонента

#javascript #vue.js #vue-component

#javascript #vue.js #vue-компонент

Вопрос:

Я знаю, как использовать контролируемые компоненты для получения выбранного значения. Например,

 // app-select.vue

<v-select :items="[1,2,3]"  @change="$emit('input', $event)"></v-select>

// parent-component.vue

<app-select v-model="selectedValue" />
  

Таким образом, изменение значения v-select должно измениться selectedValue в родительском компоненте.

Но что, если у меня есть объект, который я хотел бы обновить контролируемым компонентом с несколькими селекторами:

родитель-comp.vue

 <template>
  <filter-comp> v-model="filterObj"</filter-comp>
</template>
<script>
  import FilterComp from './filtercomp'
  export default {
    components: {
      FilterComp
    },
    data () {
      return {
         filterObj: {}
      }
    }
  }
</script>
  

и дочерний элемент с несколькими входами, способный выдавать при вводе:

 <template>
   <v-select :items="filterOneItems" @change="$emit('input', $event)">></v-select>
   <v-select :items="filterTwoItems" @change="$emit('input', $event)">></v-select>
</template>
  

И, допустим, моей целью было бы сделать так, чтобы при вводе v-select он обновлялся в родительском компоненте следующим образом:

 filterObj: {
   filterOne: 'value 1',
   filterTwo: 'value 2'
}
  

Есть ли способ заставить это работать?

Ответ №1:

Я могу придумать два решения. Первое решение, просто используйте prop, а не двустороннюю привязку:

Для parent-comp.vue

 <filter-comp :obj="filterObj"></filter-comp>
  

И для filter-comp.vue

 <template>
  <div>
    <v-select :items="items" v-model="obj.filterOne"></v-select>
    <v-select :items="items" v-model="obj.filterTwo"></v-select>
  </div>
</template>
  
 ...
  props: {
    obj: {
      type: Object,
      default: {}
    }
  }
...
  

JSFiddle

Второе решение, используйте v-model так, как вы описали:

Для filter-comp.vue

 <template>
  <div>
    <v-select :items="items" @change="change('filterOne', $event)"></v-select>
    <v-select :items="items" @change="change('filterTwo', $event)"></v-select>
  </div>
</template>
  
 ...
  methods: {
    change(name, value) {
      this.$emit('input', {
        ...this.value,
        [name]: value
      })
    }
  }
...
  

JSFiddle