これにより絵文字ボタンがコンポーネント化され、再利用可能なボタンとなりました。
それぞれのボタンに絵文字が表示され、クリックするとクリックされたボタンのカウンターが増えます。似たようなコードがなくなりスッキリしました。
絵文字ボタンのコンポーネントはできましたが、トータルのカウンターは機能しなくなりました。絵文字ボタン・コンポーネントのカウンターの合計だけロゴ(/components/Logo.vue
) コンポーネントを回転する機能がありましたが、現在は回転しません。
これまではページ側(/pages/index.vue
) に、すべての情報があったのでボタン・クリック数の合計をロゴ・コンポーネントに送れました。しかし各カウンターが絵文字ボタン・コンポーネントへ移動してしまったため、カウンターの合計がページ側では作れなくなりました。
そこで、絵文字ボタン・コンポーネント(子コンポーネント)はクリックされたことを、ページ(親コンポーネント)へ伝えるようにします。ページ側では、その各絵文字ボタン・コンポーネントから伝えられたクリックの回数をカウントして合計としてロゴ・コンポーネントへ送るようにします。
そのクリックされたことを伝えるために「イベント」を使います。絵文字ボタン・コンポーネント(子コンポーネント)から、ページ(親コンポーネント)へ「イベント通知」をすることで、クリックされたことを伝えます。
絵文字ボタン・コンポーネントのカウントアップ処理にイベント通知this.$emit('countup')
を追加します。
/components/EmojiButton.vue
(該当箇所のみ抜粋)
1 | <script lang="ts"> |
$emit
は、Vue コンポーネント間でイベントを通知するための仕組みです。今回は絵文字ボタン・コンポーネントが子コンポーネントなので、親コンポーネントであるページへイベントを通知します。
イベント通知は$emit('イベント名', [...引数])
の書式です。引数は可変長配列で、イベントの通知先へ渡されます。今回はcountup
という名前のイベント名で引数無しの通知を行っています。
参考情報
親コンポーネントであるページ側で、子コンポーネントである絵文字ボタン・コンポーネントからのイベント通知を受け取ります。
/pages/index.vue
(該当箇所のみ抜粋)
1 | <template> |
<emoji-button>
タグにv-on:countup="add"
属性を追加し、絵文字ボタン・コンポーネントのcountup
イベントを受け取ります。属性値add
は、メソッド呼出しでadd()
メソッドを呼び出すという定義です。これにより子コンポーネントのイベントを受け取って、親コンポーネントで処理をするという形が作れます。
上記定義で呼び出されるメソッドを<script>
に追加します。これは通常のメソッド定義と同様です。今回はdata() { total }
をインクリメントするメソッドとします。
これにより各絵文字ボタン・コンポーネントがクリックされると、ページ側にcountup
イベントが伝わります。そのイベントの回数をtotal
にインクリメントしていくことで、全絵文字ボタン・コンポーネントのカウンター合計が作れます。
そしてtotal
をcomputed: { counter() }
につなぐことで、これまで機能していたロゴの回転が復旧します。
参考情報
最後に [Clear] ボタンを復旧します。[Clear] ボタンは絵文字ボタンと異なり1つだけですし、すべての絵文字ボタン・コンポーネントのカウンターをリセットする特別な役割があります。そのため親コンポーネントに残しました。
[Clear] ボタンの機能であるリセットですが、親コンポーネント内のtotal
を0
にリセットすることはできます。それによりロゴの回転を止めて、カウンターのリセットもできます。
しかしながら子コンポーネントのカウンターは直接リセットできません。こちらもイベント通知を使いリセットします。先ほどと逆なり、親コンポーネントから子コンポーネントへイベントを通知します。
ページ側はイベントを通知する先の子コンポーネントである、全絵文字ボタン・コンポーネントを特定してイベント通知します。今回は絵文字ボタン・コンポーネントしかないので(正確には、ロゴ・コンポーネントも子コンポーネントですが)、送り先を意識しにくいですが多数のコンポーネントを抱えている親コンポーネントであるからこそ、どのコンポーネントへイベント通知するか考える必要があります。
/pages/index.vue
(該当箇所のみ抜粋)
1 | <template> |
<emoji-button>
タグのref="EmojiButtons"
属性は、EmojiButtons
の文字列でタグを参照されるための設定です。ref
属性は通常の HTML タグと、子の Vue コンポーネント・タグのどちらにも使用できます。
参照する側は$refs.[ref 属性の値]
で行います。今回はEmojiButtons
で登録したので$refs.EmojiButtons
でアクセスします。clear()
メソッドではEmojiButtons
で登録された全絵文字ボタン・コンポーネントを取得し、$emit('clear')
でclear
というイベント名で引数無しの通知を送っています。$emit()
の使い方は、子コンポーネントからイベントを送った時と同じです。
参考情報
絵文字ボタン・コンポーネントで clear
イベントの通知を受けます。
/components/EmojiButton.vue
(該当箇所のみ抜粋)
1 | <script lang="ts"> |
Vue コンポーネントのライフサイクルcreated
で、$on
を使い、イベント受け取りの登録をしておきます。今回は、イベント名clear
で引数無しです。イベントを受けたらコンポーネント内のcounter
をリセットします。これにより、各絵文字ボタン・コンポーネントのカウンターがクリアできます。
参考情報
今回作成した部分までのソースを GitHub へアップしました。(Tag:0.0.5
)
GitHub Pages にホスティングもしました。動作している状態を確認する場合は、こちらへアクセスしてください。
(公開サイトは1つのため記事公開に合わせて変わり、本記事の内容とは異なることがあります)
似たようなコードをコンポーネント化し再利用できるようにしました。Vue コンポーネントを使うことで、画面内のコードもスッキリさせることができます。(同じようなものは集約してプログラムで処理したいところですよね、0.0.4 までのソースはサンプル用とはいえ心苦しかった)
一方でコンポーネント間の連携は意外と難しいところがあります。まずは親子間のイベント通知が基本です。
今回のサンプルは、スタータープロジェクトにボタンを付けたり、ロゴを回したりと地味な感じではありますが、2種類の子コンポーネント間を親コンポーネントがつなぐ形となっています。まさにコンポーネント間連携の基本なので、実装を確認いただければと思います。
[Clear] ボタンが子コンポーネントになると、兄弟間の連携となり、また一歩踏み込むことになりますが次の機会に!