【Nuxt.js】ネストしたコンポーネントでv-modelの変更を親に反映させる

1 min read

概要

以下のような、下位のv-modelの変更をさらに上位のv-modelに反映させるためのバケツリレー行う方法です。
<親コンポーネント>

<子コンポーネント v-model>

<input v-model>

実装方法

  1. 子コンポーネントに、親にv-modelでバインドされた値を受け取るためのプロパティを定義します。
model: {
  prop: 'model',
  event: 'change'
},
props: {
  model: {
    type: String,
    default: ''
  }
}

model.proppropsのプロパティ名が一致するよう定義します。

  1. 子コンポーネントのcomputedに、getter/setterを持つプロパティを定義し、inputのv-modelにバインドします。
    (propsで受け取ったデータを直接v-modelにバインドさせることができないので、getter/setterを経由させて間接的にバインドさせています。)
    setterは、inputに入力されるたびに実行され、親コンポーネントへchangeイベントで値の変更を通知します。
<input v-model="_model">
computed: {
  _model: {
    get () {
      return this.model
    },
    set (value) {
      this.$emit('change', value)
    }
  }
}
  1. 親コンポーネントで、子コンポーネントのv-modelに変数をバインドする。
    (ここはいたって普通)

まとめると以下のようになります。

  • 親コンポーネント
<template>
  <div>
    <MyComponent v-model="inputModel" />
  </div>
</template>

<script>
export default {
  data () {
    return {
      inputModel: ''
    }
  }
}
</script>
  • 子コンポーネント
<template>
  <div>
    <input v-model="_model">
  </div>
</template>

<script>
export default {
  model: {
    prop: 'model',
    event: 'change'
  },
  props: {
    model: {
      type: String,
      default: ''
    }
  },
  computed: {
    _model: {
      get () {
        return this.model
      },
      set (value) {
        this.$emit('change', value)
      }
    }
  }
}
</script>