LoginSignup
0
0

More than 1 year has passed since last update.

Nuxt Composition Api x TypeScript で親子コンポーネント間で computed を使って双方向バインディングする

Last updated at Posted at 2021-09-16

2年前に Vue.js を触ったときに computed で双方向バインディングを実装した覚えがあったけど、
完全に抜けてたし、Composition Api x TypeScript は初めてだったので、未来の自分のために備忘録を残します。

実際のコード

親コンポーネントでは,v-model にリアクティブな値を渡す。

親コンポーネント
<template>
  <div>
    <TextForm v-model="value" />
  </div>
</template>

<script lang="ts">
import {defineComponent, ref} from '@nuxtjs/composition-api';

export default defineComponent({
  components: {
    TextForm
  },
  setup() {
    const value = ref(10);
    return {value}
  }
});
</script>

子コンポーネントでは、
1. 親からv-modelで渡された値は、props.valueで受け取れる。
2. setup() の引数で emit を指定する。
3. computed で、valuegetter/setter を用意する。
4. setteremit する。
5. computed の値を <input>v-modelにわたす。

子コンポーネント
<template>
  <label>
    <input v-model="v">
  </label>
</template>

<script lang="ts">
import {computed, defineComponent} from '@nuxtjs/composition-api';

export default defineComponent({
  name: 'TextForm',
  props: {
    value: {
      type: Number,
      default: 0
    },
  },
  setup(props, {emit}) {
    const v = computed({
      get: () => props.value,
      set: (newValue) => {
        emit('input', newValue);
      }
    });
    return {v};
  }
});
</script>

ちなみに、今回 value の型が numberで、setterの引数も number として推論されるのですが、
フォームを一度空にしたり、マイナスの値を入力しようとすると、一時的に string型が渡されエラーを吐きます。
なので、以下の通り型指定をして、対応しました。

子コンポーネント
<script lang="ts">
... 中略 ...
  setup(props, {emit}) {
    const v = computed({
      get: () => props.value,
      set: (newValue: number | '' | '-' | '.') => {
        const number = parseFloat(String(newValue));
        if (!Number.isNaN(number)) {
          emit('input', number);
        }
      }
    });
... 中略 ...
</script>

参考

【Vue】Avoid mutating a prop directlyエラーの発生原因と対処法

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0