Как правильно сделать v-model у компонента?

InputName.vue

<template>
  <el-form-item label="Название" prop="name">
    <el-input :value="name" @input="updateName"></el-input>
  </el-form-item>
</template>

<script>
export default {
  name: "InputName",
  props: ["name"],
  methods: {
    updateName() {
      this.$emit("input", name);
    }
  }
};
</script>

Используется в форме

<el-form ref="form" :model="form">
   <input-name v-model="name" />
</el-form>

Пишет что 'Property or method "name" is not defined'. В чем моя ошибка, и как сделать чтобы все работало?


Ответы (1 шт):

Автор решения: Николай Парахневич

В официальной документации Vue - Использование v-model на компонентах подробно описано, как работает v-model на компонентах:

Не забывайте, что:

<input v-model="searchText">

делает то же самое, что и:

<input v-bind:value="searchText" v-on:input="searchText = $event.target.value">

При использовании на компоненте, v-model делает следующее:

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

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

  1. Привязывать значение атрибута value к входному параметру value
  2. По событию input генерировать собственное пользовательское событие input с новым значением

К сожалению в вашем коде не описаны все используемые вами компоненты (что не дает возможности проанализировать код), поэтому приведу наглядный пример двунаправленной связи между компонентами через v-model:

Vue.component('input-name', {
  props: ["value", "name"],
  methods: {
    updateName(e) {
      this.$emit("input", e.target.value);
    }
  },
  template: `
  <div>
  <label>
    [component - input-name] {{ name }}
    <input :value="value" @input="updateName"></input>
  </label>
  </div>
`
})
Vue.component('el-form', {
  props: ["value"],
  template: `
  <div>
  [component - el-form]
  <pre>{{ JSON.stringify(value, 0, 2) }}</pre>
  <hr>
  <slot name="default"></slot>
  </div>
`
})

const app = new Vue({
  el: '#app',
  data: {
    form: {
      name: 'Test Name',
      family: 'Test Family'
    }
  }
})
div {
  padding: 10px;
  margin: 5px;
  background: rgba(0, 0, 0, .1)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
  <el-form ref="form" v-model="form">
    <input-name v-for="(field, key) in form" :key="key" :name="key" v-model="form[key]" />
  </el-form>
</div>

→ Ссылка