会員登録ページは全4回に渡って構築します。
1/4 レイアウトファイルの作成
2/4 名前、メールアドレス、パスワードコンポーネントの作成
3/4 親子コンポーネント間のデータ通信設定(今ここ)
今回達成すること
前回は「名前」、「メールアドレス」、「パスワード」の3つのコンポーネントファイルを設置しました。
今回は、その親子コンポーネント間でデータ通信を行う設定をします。
もう少し詳しく言うと、
- 親となる
signup.vue で用意したデータを、 - 子となる各フォームコンポーネントで編集し、
- 親のデータをリアルタイムで更新する
設定です。
最終的には、フォームに入力された値が
signup.vueにRailsへ送信するオブジェクトを用意する
まずはparams
オブジェクトを用意します。
front/pages/signup.vue
...
export default {
layout: 'beforeLogin',
data () {
return {
isValid: false,
// 追加
params: { user: { name: '', email: '', password: '' } }
}
}
}
そして、それぞれのデータをバインドで各コンポーネントに送信します。
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"
/>
...
</template>
...
sync修飾子を理解しよう
親子コンポーネント間のデータ送受信では、通常このように書きます。
通常
<user-name-form
:name="params.user.name"
@update:name="params.user.name = $event"
/>
- バインド
:name
で親 → 子へデータを送信し、 - 子でデータを編集。
- 子から編集後のデータを送信し、
- 親は
@update:name
で受け取り、"params.user.name = $event"
で値を代入する。
通常この流れになるのですが、sync修飾子を使えば省略して書くことができます。
sync修飾子
<user-name-form
:name.sync="params.user.name"
/>
双方とも、やっている事は同じです。
子コンポーネントでデータを受け取る
props
を使って、親から送信されたデータを子コンポーネントで受け取りましょう。
front/components/user/userFormName.vue
...
export default {
// 追加
props: {
name: {
type: String,
default: ''
}
}
}
front/components/user/userFormEmail.vue
...
export default {
// 追加
props: {
email: {
type: String,
default: ''
}
}
}
front/components/user/userFormPassword.vue
...
export default {
// 追加
props: {
password: {
type: String,
default: ''
}
}
}
親のデータを子コンポーネントのv-modelで更新する
子コンポーネント側で更新した値を、親コンポーネントでリアルタイムで受け取るために、Vueのv-model
を使用します。
原則
Vue.jsの仕様で、
- 親コンポーネントのデータを、
- 子コンポーネント側の
v-model
を使って - 更新させる事はできません。
対応
しかし、
- データの受信と
- データの送信を
- 切り分けることで
v-model
を使った更新を実現できます。
まずは、
front/components/user/userFormName.vue
<template>
<!-- v-model 追加 -->
<v-text-field
v-model="setName"
label="ユーザー名を入力"
placeholder="あなたの表示名"
outlined
/>
</template>
<script>
export default {
...
// 追加
computed: {
setName: {
get () { return this.name },
set (newVal) { return this.$emit('update:name', newVal) }
}
}
}
</script>
-
setName: {}
...computed
の中でオブジェクトを宣言し、データの受信と送信を切り分ける。-
get()
... 親から受信したデータを返す。この
get()
を、ゲッター関数と言います。 -
set(newVal)
... 子で編集した値を送信する。この
set()
を、セッター関数と言います。セッター関数の引数には、変化後の(最新の)値が入っています。
-
-
v-model="setName"
...v-model
には、computed
で作成した算出プロパティを指定する。親のデータ
name
を直接指定するとエラーになります。
確認してみよう
params
を表示させて、名前フォームを入力してみましょう。
front/pages/signup.vue
....
</v-form>
<!-- 追加 -->
<v-card-text>
{{ params }}
</v-card-text>
<!-- ここまで -->
</bef-login-form-card>
</template>
コンテナを起動して、http://localhost:8080/signup にアクセスしてください。
親のデータが、子コンポーネントを経由して、リアルタイムで更新されるようになりました。
email、passwordコンポーネントにもv-modelを追加する
同じようにv-model
を追加しましょう。
front/components/user/userFormEmail.vue
<template>
<v-text-field
v-model="setEmail"
label="メールアドレスを入力"
placeholder="your@email.com"
outlined
/>
</template>
<script>
export default {
props: {
email: {
type: String,
default: ''
}
},
computed: {
setEmail: {
get () { return this.email },
set (newVal) { return this.$emit('update:email', newVal) }
}
}
}
</script>
front/components/user/userFormPassword.vue
<template>
<v-text-field
v-model="setPassword"
label="パスワードを入力"
placeholder="8文字以上"
outlined
/>
</template>
<script>
export default {
props: {
password: {
type: String,
default: ''
}
},
computed: {
setPassword: {
get () { return this.password },
set (newVal) { return this.$emit('update:password', newVal) }
}
}
}
</script>
これで全ての子コンポーネントで、リアルタイム更新が可能になりました!
コミットしとく
以上で作業は終了です。
「front」ディレクトリに移動して、コミットしておきましょう。
root $ cd front && git commit -am "signup_page_set_data_building" && cd ..
まとめ
今回は、親子コンポーネント間のデータ通信を実装しました。
コンポーネント間のデータ通信はNuxt.jsというか、Vue.jsの基本です。
今後、様々な場所で使用するので、ここの知識は大切にしておきましょう。
次回は?
それぞれのフォームに、Vuetifyを使ったバリデーションを設定します。
サーバーサイドのRailsにデータを送信する前に、フロントエンドでバリデーションをしておくことで、ユーザーのストレスを軽減させることができます。
いよいよ会員登録ページも大詰め!(Go To Next!!)