【Vue】Input内の値をv-modelのように親子間でバインドさせる方法【サンプルあり】

どーも、ぐるたか@guru_takaです。

Vueにて、子コンポーネント内にあるInputの値を、親コンポーネントにバインドさせる方法をまとめました。

よくある間違いも紹介しています。参考になれば幸いです!

v-modelに親からデータ渡すだけではアウト!

以下のコードはやりがちですが、うまく動きません。

子コンポーネント
<template>
  <input v-model="value" />
</template>
<script>
export default {
  props: ['value']
}
</script>
引用:Vue.js:v-modelと$emitを使ってデータを読み書きする子コンポーネントをつくる

なぜなら、valueは親から渡されたpropsなので、Read onlyだからです。

子コンポーネントで変更したい値を親コンポーネントに渡すには、一工夫、必要になります。

親子間でInput内の値をバインドさせる方法

まずはコードから!

子コンポーネント
<template>
  <input 
    :value="value"
    @input="$emit('input', $event.target.value)"
  />  
</template>

<script>
export default {
  props: ['value']
}
</script>
親コンポーネント
<template>
  <div>
    <InputChild
      :value="value"
      @input="value = $event"
    ></InputChild>
  </div>
</template>

<script>
import InputChild from '@/components/InputChild'

export default {
  components: {
    InputChild
  },
  data() {
    return {
      value: ''
    }
  },

}
</script>

以下の記事を参考にしています。
参考 Vue.js:v-modelと$emitを使ってデータを読み書きする子コンポーネントをつくるQiita

簡単な解説

v-modelの仕組み

v-modelは以下のコードのように分解できます。

<syntax-sugar v-model="cup"></syntax-sugar>
<syntax-sugar :value="cup" @input="val => cup = val"></syntax-sugar>
引用:Vue.js:v-modelと$emitを使ってデータを読み書きする子コンポーネントをつくる

v-modelは、Input内の値が変更されると、@inputが発火し、値が更新される仕組みになっています。

なので、親子間でデータをバインドさせる時は、v-modelではなく、:value@inputをうまく使ってあげれば、良いのです!

$event$event.target.valueについて

$event$event.target.valueは公式に、お作法が載っています。

Inputタグの場合
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>
オリジナルのコンポーネントの場合
<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

簡単にまとめると

  • inputタグの場合は、$event.target.valueで値を更新
  • 独自コンポーネントの場合は、$eventで値を更新

になります。

参考 コンポーネントの基本Vue.js

最後に

以上になります。個人的ですが、v-modelの中身や@inputの仕組みも理解できて良かったです!

ぜひお試しください!

コメントを残す