初学者がVue.jsで掲示板サイトを作ってみた
作ってみた
WEBの勉強を始めて早数か月、グダグダインプットを続けるよりもさっさとアウトプットをしてしまおうということで作ってみました。(Qiitaに投稿する勇気はありませんでした...…)
ちなみに参考書籍はこちら。
基礎から学ぶ Vue.js | MIO | 工学 | Kindleストア | Amazon
Amazon.co.jp: Webデザインの現場で使えるVue.jsの教科書 eBook: 廣末丈士, 遠山恭平: Kindleストア
プロダクト概要
アプリはGithub Pagesを用いて公開しております。
https://noritama73.github.io/personal-development/vue-chat/index.html
リポジトリはこちら
github.com
ぶち当たった壁たち
Vue初心者の私が製作途中でぶち当たったエラーなどを思い出せる限り書いていきます。
1.v-forで記述した要素はkeyを指定する
エラー文の表示にアニメーションを指定するのにtransition-groupタグを使用しましたが、その際v-forにkey属性を指定する必要があるみたいです。自分が指定したkeyについては Duplicate keys detected... というエラーが出てきてしまいますが、コンパイルや動作に問題はなかったので素通りしました。当然あんまりよくないと思います。
2.レスごとに返信用プロパティを指定・操作する
当初はmessageコンポーネントからreplyMessageコンポーネントに返信テキストのプロパティを渡していましたが、それだとreplyMessage全体に同じプロパティが渡ってしまいました。そこでreplyMessageコンポーネント内でそれらのプロパティを指定し、必要な操作は親から行う形にしました。3.につながります。
3.子のメソッドを親から動かす
返信の操作を始めるボタンはもちろんmessageコンポーネント、つまり親側に置く必要がありますが、前述の通りプロパティ自体は子側にあります。そこで親から子にrefでレファレンスIDを渡し、子側のコンポーネントを呼び出す形を取りました。
<reply-message :reply-id="chat.id" ref="child"></reply-message>
とrefで渡して
openReply(index) { this.$refs.child[index].openReplyChild(); }
と呼び出し、
openReplyChild() { this.isReply = true; }
を呼び出します。
ここで this.$refs.child[index] としているのは、v-for内でrefを使用しているため、childがコンポーネントごとに配列のような形で渡されているからだそう。詳しくは↓
qiita.com
4.配列のうち、該当する要素を含むものを削除する
レスを削除する際、削除ボタンが押されたレスのIDを取得し、レスのプロパティを保持するchats配列からそのIDに該当する部分を削除する処理をしています。コードは以下。
this.chats = this.chats.filter( x => x.id !== did);
削除したい部分を取り除くのではなく、残したい部分を引き抜いてそれで配列全体を上書きするというやり方です。こういうところで愚直に実装しようとしてはいけない。
ちなみに冒頭で説明したバグ仕様はこの処理と上手く結び付けられずに発生したものです。着想の段階でここら辺まで吟味してデータ構造を考えるべきでした...…
5.ビルドする
ページ遷移すら必要ない簡易なアプリなので、webpack-simpleを用いて作成しました。ビルドの際はvue.config.jsを以下のように作成。
module.exports = { publicpath: './' }
これに応じて、index.htmlも少し弄ります。
<script src="./dist/build.js"></script>
(こちらはもしかしたら不要かも)
これでビルドの際に各ファイルを相対パスで読み込めます。webpack.config.jsにも似た記述がありますが、そちらの編集は必要なのか不明です。再現するのがめんどくさい
おわりに
書籍のサンプルを見よう見まねでこねくり回してなんとか完成に漕ぎつけました。細かい妥協は、「これ以上頭を抱えてもモチベを無くすだけだ」という切り替えだと思っていただければ。とりあえず載せるものができたので、次はポートフォリオサイトをちゃんと書こうかと思います。
それでは。