【Vue.js超入門】つぶやき機能チュートリアル(CRUD)

vue.js tutorial

2022年8月28日

これからVue.jsに触っていく方向けに、短時間で手軽に学べるチュートリアルを作成しました。
所要時間はおよそ50分程度を目安にしています。

こちらのチュートリアルでは『つぶやき機能』を作って、Vue.jsの基礎的な機能と一通りのCURD機能の実装を経験しましょう!

目次

  1. 環境構築
  2. Vue.jsの導入
  3. dataオプションにデータを定義し、画面に表示してみよう
  4. メソッドを作成してclickイベントを作る
  5. v-modelを使ってフォームの値を取得しよう
  6. v-ifで条件分岐、v-forで繰り返し処理をする
  7. 編集機能を実装しよう

チュートリアル

環境構築

今回利用する技術は下記になります。

  • Vue.js3(CDN最新版)
  • Bootstrap4.6(CDN):デザイン
  • Fontawesome(CDN):アイコン

本格的にVue.jsを導入する際は.vueファイルを作成し、npmで最終的にjsにコンパイルして実装していきますが、今回は簡易的に触りたいため、Vue.js自体はCDNで読み込み、jsファイルに記述していきます。

以下のコマンドを実行してファイルをダウンロードしてください。

$ git clone git@github.com:juno1140/vue-tutorial.git

ダウンロードできたら、エディタで開いてみましょう。

今回記述していくファイルはプロジェクトルートディレクトリに存在するindex.htmlとmain.jsです。

completeディレクトリには完成形のコードがあるので参考にして進めてください。

ではまずindex.htmlをブラウザで開いてみましょう。

以下のようになっていたらOKです。

つぶやきを投稿するフォームとつぶやきの一覧がある状態です。

編集を押すと、モーダルが表示されますが、こちらはBootstrapで組み込まれています。

これで準備は完了です。
まだ動的には動かないのでここからVue.jsを導入して動的なサイトにしていきましょう!

ちなみに私のエディタはVSCode、プレビュー画面にはVSCodeの拡張機能「Live Preview」を使っています。

Vue.jsの導入

まずはVue.jsを導入しましょう。

今回はCDNを利用してVue.jsのプログラムを読み込みます。下記のようにbodyタグ上の<script src="main.js"></script>の上にコードを追加します。

       <script src="https://unpkg.com/vue@next"></script> ⇦追加
    <script src="main.js"></script>
</body>

これで準備完了です。

Vue.jsをHTMLに組み込むにあたり、Vue.jsの操作範囲対象とするHTMLタグにidを付与します。

今回は、操作範囲対象とするidに「app」を指定しようと思います(appでなくても問題ないです。このidはVue.jsを記述する際に指定します)。

ではbodyタグ直下のdivタグにid="app"を記述してください。

<body>
    <div id="app">

これで、このdivタグの中のタグはVue.jsで操作可能になります。

ではmain.jsにVue.jsを記述していきましょう。

const app = Vue.createApp({
    
})
  
app.mount('#app')

appという定数を定義し、その中にVueのインスタンスを格納します。インスタンスの作成にはVue.createAppと記述します。この中に、Vueのプロパティや処理を記述していきます。

そして、HTMLにマウント(反映)していきます。マウントはapp.mount()と記述し、引数に先ほど指定したidを入れます。

これでVue.jsの導入は完了です。

dataオプションにデータを定義し、画面に表示してみよう

Vueの導入が終わったところで、次はdataオプションにデータを定義してみましょう。

dataオプションには数値や文字列などの値、オブジェクト、関数などを指定することができます。

dataオプションは、次の書式で定義します。Vue.createAppの中に以下のように定義しましょう。

const app = Vue.createApp({
  data() {
    return {
      title: "ホーム",
    };
  },
});

dataオプションはfunctionの形で定義します。そして、その中に、titleというデータを定義し、"ホーム"という文字列を指定しました。

titleというのは変数だと思っていただけると理解しやすいと思います。

title変数に文字列の「ホーム」が格納されている状態です。

では、titleを画面に描画してみましょう。

index.htmlの「ホーム」という文字列を以下のように変更してください。

<label for="exampleFormControlTextarea1">{{ title }}</label>

{{ }}のことをマスタッシュ記法と言います。

Vue.jsで定義したdataを表示する際はマスタッシュを使って表示することができます。

ブラウザを見てみましょう。変わらず「ホーム」と表示されていればOKです。

メソッドを作成してclickイベントを作る

次にメソッドを定義していきましょう。methodsを記述します。

const app = Vue.createApp({
  data() {
    return {
      title: "ホーム",
    };
  },
  methods: {
  }
});

各メソッド(関数)はこのmethodsの中に記述していきます。

ではstoreメソッドを作成してみましょう。

methods: {
  store() {
      alert('Hello Vue');
  },
},

storeが実行されるとalertが表示される処理です。

画面の「ツイートする」ボタンを押したときに、このstoreメソッドが実行されるようにしましょう。

タグにclickイベントを付与する場合、@clickを記述します。

<button class="btn btn-primary" @click="store">ツイートする</button>

「ツイートする」ボタンを押してalertが出ればOKです(Live Previewでは出ないかもしれません)。

v-modelを使ってフォームの値を取得しよう

では、実際にツイートを投稿する処理を書いていきましょう。

投稿を保存する際、テキストエリアに入力したテキストを取得しなければいけません。

このときに利用するのがv-modelです。実際に使っていきましょう。

まず、dataにテキストエリアに入力内容を保持するtextと投稿を格納するlistというデータを定義しておきましょう。

data() {
  return {
    title: "ホーム",
    text: "",
    list: []
  };
},

textareaタグにv-modelを記述します。

<textarea
    class="form-control"
    id="exampleFormControlTextarea1"
    rows="3"
    placeholder="今どうしてる?"
    v-model="text"
></textarea>

このように記述することによって、テキストエリアに入力すると自動的にdataのtextに値が格納されます。逆にVue.js内でtextの値を書き換えるとテキストエリアに書き換えた内容が入ります。

このように画面とプログラムでお互いが双方向にデータを書き換えることを「双方向バインディング」と言います。

では、storeメソッドを書き換えていきましょう。

store() {
    this.list.push({text: this.text})
    this.text = ''
},

メソッド内でdataを利用するときはthis.を使って呼び出します。

listの配列内にはオブジェクトの形で格納していきます。

そして、投稿後はテキストエリアの中身を空欄にしています。

はい、これで投稿処理は完了です。実際に投稿してみてください。console.log(this.list)など仕込んでコンソール内を確認するとlistに格納されていくのがわかるかと思います。

v-forで繰り返し処理、v-ifで条件分岐をする

投稿を保存できたので、それを一覧に表示していきましょう。

vue.jsでループ処理をする場合はHTMLタグ内にv-forを利用します。

現在一覧はハードコーディングされている状態なので、borderクラスが付与されているブロックを1つだけにして他は削除しましょう。

そして、一覧の部分を以下のように修正してください。

<div class="timeline">
    <div v-for="item in list" class="border p-3">
        <p style="white-space: pre-wrap; word-break: break-word">{{ item.text }}</p>
〜以下略〜

これで投稿したものを一覧で表示できるようになります。実際に投稿してみてください。

ただ、なにも投稿していない状態だと一覧が真っ白になってしまいます。

何もない時は「投稿がありません。」と表示するようにしてみましょう。

この時使うのが、v-ifです。

もしもlistの配列が空なら「投稿がありません。」を表示するという処理を書いていきましょう。

<div class="timeline">
    <div v-if="list.length == 0">投稿がありません。</div>
    <div v-else v-for="item in list" class="border p-3">
〜以下略〜

v-ifの条件内にlist.lengthが0のときにこのタグが表示されます。

list.lengthが0以外のときはv-ifのタグは表示されず、v-elseのタグが表示されるようになります。

はい、これで一通りVue.jsの基礎は紹介できました。
これ以降はいままでの応用で実装していきます。

編集機能を実装しよう

では、編集機能をつくっていきましょう。

現状、編集ボタンを押すとモーダルが開くだけになっています。

この状態からモーダルを開いた時に既存のデータをテキストエリアに表示するようにし、変更ボタンを押した時に編集したテキストに反映させていきましょう。

と、その前に実は今、適切にモーダルが開いている訳ではありません。どの投稿の編集ボタンを押しても一番上の投稿のモーダルが開いてしまいます。これは各投稿ごとにユニークなidとなっていないためです。

では、各投稿ごとのモーダルと編集ボタンのidなどを編集していきましょう。

そのためにはまず、v-forのループごとにユニークなindexが必要となります。v-forを以下のように修正してください。

<div v-else v-for="(item, index) in list" class="border p-3">

このindexは0からはじまり、ループするごとに1加算されていきます。こちらを使ってユニークを実現しましょう。

<!-- 編集ボタン -->
<button
    class="btn btn-dark mx-2"
    data-toggle="modal"
    :data-target="'#exampleModal' + index"
>編集</button>
<!-- 編集モーダル -->
<div
    class="modal fade"
    :id="'exampleModal' + index"
    tabindex="-1"
    aria-labelledby="exampleModalLabel"
    aria-hidden="true"
>

上記のコードで重要な点として、HTMLタグ内の属性内でVueの変数を利用する時は属性名の先頭に「コロン(:)」を付与しなければいけません。

上記のように記述することで、「exampleModal0」「exampleModal1」…とユニークなidを指定することができ、適切にモーダルが開くようになりました。

さて、本題に戻りましょう。

まず、各モーダル内のテキストエリアの入力を保持するpreTextという項目を設定しましょう。
listに保存するオブジェクト内にpreTextという項目を追加してください。

store() {
    this.list.push({text: this.text, preText: this.text})
    this.text = ''
},

登録時はpreTextに入力した内容と同じものを設定しておきます。
そして、このpreTextをモーダル内のテキストエリアのv-modelに設定し表示します。

<div class="modal-body">
    <textarea
        class="form-control"
    id="exampleFormControlTextarea1"
        rows="3"
        v-model="item.preText"
    ></textarea>
</div>

これで、モーダルを開くとその投稿のテキストが表示されるようになったかと思います。

では次に編集を実行するメソッドupdateを定義しましょう。

update(index){
    this.list[index].text = this.list[index].preText
    document.getElementById("exampleModal" + index).click();
},

updateメソッドの引数でindexを受け取り、対象のlistのtextに編集したpreTextが入るようにしています。これで更新は完了です。

処理の2行目ではモーダルを閉じる処理を記述しています。

あとは変更ボタンを押した際にupdateメソッドが実行されるよう、ボタンに@clickを付与しましょう。

<button type="button" class="btn btn-primary" @click="update(index)">変更</button>

これで編集まで完了です。

削除処理

では最後に、削除処理を作っていきましょう。

削除処理も今までやってきたことの応用でできます。

deleteText()というメソッドを追加しましょう。
(尚、deleteという名前は(予約語となっているため?)メソッド名としては利用できません。)

deleteTweet(index){
    this.list.splice(index, 1);
},

jsで配列の削除にはspliceを使っていきます。

あとは削除ボタンに@clickを記述するだけです。

<button class="btn btn-danger mx-2" @click="deleteText(index)">削除</button>

これで削除まで完了です。

おまけチャレンジ

おまけとして、いいね機能も実装してみましょう。

顔の絵文字をクリックすると数字が増えていくようにします。

こちらは紹介しませんが、これまでの実装ができれば簡単に実装できるのではないかと思いますのでチャレンジしてみてください。

まとめ

お疲れ様でした。うまく実装できましたか?

基本的に今回紹介した機能がメインになっていきます。曖昧なところは他の記事なども参考にさらに理解を深めていってください。

さらに本格的にVue.jsを使っていこうする場合はもう少し知識を広げる必要があるので参考書などを買って勉強してみてください。