.syncのここが凄い!

コンポーネント間で値を受け渡しする流れが一生分からない。悩んでも仕方ないから、とりあえずインプット量を増やす。てなわけで、今回は.syncに関して学習していく。

 

.sync修飾子のどこが凄い?

 v-bind:title="doc.title"
 v-on:update:title="doc.title = $event"

この書き方を、以下のようにまとめることができるところ。

 :title.sync="doc.title"

.sync修飾子って何?

vueのカスタムイベントの一つ。

親が子に渡した値Aを、子が編集し、編集後の値Aを子から親に返す。

.syncを使うことで、受け取った値Aを親は親は比較的少ない記述量で反映させることができる。

どう使うんですか?

下記のように、v-bindに対して使う。

<text-document 
  :title.sync="doc.title"
></text-document>

公式Docを見て学習していく。

子は、methodで下記のように記述することで、titleのアップデートを親に送ることができる。

this.$emit('update:title', newTitle)

$emitを使ってnewTitleをupdate:titleに反映させて親に渡している。親は$eventで受け取ることができる。

親は、下記のように$eventを記述することでupdate:titleを取得している。

<text-document
  :title="doc.title"
  @update:title="doc.title = $event"
></text-document>

このパターンを .sync 修飾子で短く書くことができる。

<text-document 
  :title.sync="doc.title"
></text-document>

もっと分かりやすい記事ないの?

あります。

参考記事にあった、ユーザーのログインフォームを実装を通して理解を深めてみる。

コンポーネント

front/pages/signup.vue


<template>
      ...
      <!-- :name.sync 追加 -->
      <user-form-name
        :name.sync="params.user.name"
      />
      <!-- :email.sync 追加 -->
      <user-form-email
        :email.sync="params.user.email"
      />
      <!-- :password.sync 追加 -->
      <user-form-password
        :password.sync="params.user.password"
      />
export default {
  layout: 'beforeLogin',
  data () {
    return {
      isValid: false,
      // 追加
      params: { user: { name: '', email: '', password: '' } }
    }
  }
}

UserNameForm

<user-name-form
  :name="params.user.name" # : はv-bindの省略形
  @update:name="params.user.name = $event" # @はv-onの省略形
/> 
  1. バインド:nameで親 → 子へデータを送信し、
  2. 子でデータを編集。
  3. 子から編集後のデータを送信し、
  4. 親は@update:nameで受け取り、"params.user.name = $event"で値を代入する。

通常の書き方は上記のようになるが、.sync修飾子を使うと下記のように書くことができる。

<user-name-form
  :name.sync="params.user.name"
/>

子⇨親の連動バインディングが.syncで省略されている。

@update:nameで子から編集後のデータを受け取って$eventで親の該当箇所を更新する、という処理が.syncで完結できている。

ちなみに、v-bind は「:」v-onは「@」v-slotは「#」という記述ができる。

front/components/user/userFormName.vue

<template>
  <!-- v-model 追加 -->
  <v-text-field
    v-model="setName"
    label="ユーザー名を入力"
    placeholder="あなたの表示名"
    outlined
  />
</template>
<script>
export default {
props: {
    name: {
      type: String,
      default: ''
    }
  }
computed: {
    setName: {
      get () { return this.name },
      set (newVal) { return this.$emit('update:name', newVal) }
    }
  }
}
</script>
  1. v-modelに入力されたStringの値は、setNameに保存される。
  2. setNameにはgetterとsetterの二つがある。
  3. getterを通して、prop(親⇨子の値を受け取ることができるプロパティ )のnameにアクセスすることができる。
  4. getterで取得したthis.nameは、v-modelに入力された値に更新される。
  5. 更新された値はnewValとしてsetterに入り、this.$emit('update:name', newVal)によって親に渡される。

まとめ

  • .syncを使うことで、子から$emitされた値を親は簡潔な記述で受け取ることができる。
  • v-bind は「:」v-onは「@」v-slotは「#」
  • propは親⇨子の流れで値が移動する。

カスタムイベント - Vue.js

Nuxt.js 親子コンポーネント間の双方向データバインディングを実装する(3/4) - 独学プログラマ