Vue:ゼロから始めるWebアプリ開発 第4回

こんにちは、TakahiRoyteです!今回はいよいよVue.jsとJavaScriptファイルをToDoアプリに組み込んでいきます。早速コーディング開始です。

JavaScriptファイルを組み込む

まずはディレクトリを準備しましょう。各種ライブラリ用のlibディレクトリとJavaScript用のjsディレクトリを作成してください。次に肝心のvue.jsファイルをダウンロードします。下記リンクに飛んで「スタンドアロン」の項目にある開発バージョンをクリックしてファイルをダウンロードしてください。

Vue.js インストール

ダウンロードしたらlibディレクトリの中にvue.jsを格納しましょう。次はjsディレクトリ内にapp.jsファイルを作成してください。app.jsには試しにconsole.log('JavaScript loaded!');と記入しておきましょう。

todo
├css
│└milligram.css
├js ★
│└app.js ★
├lib ★
│└vue.js ★
└index.html

上記の構成が完了したら、HTML側から各JavaScriptをscriptタグで読み込んであげる必要があります。下記のように、bodyの閉じタグの直前にscriptタグを使って読み込んでください。

JavaScript読み込み

正常に読み込めたかを確認するためにChromeの開発者画面を開いてみましょう(F12ですよ!)。開発者画面上側のメニュー欄にConsoleがあると思います。これを選択してください。以下の3つのログは出ていますか?

  • You are running Vue in development mode.(以下略)
  • JavaScript loaded!
  • Download the Vue Devtools(以下略)

表示されていたらJSの読み込みができています!

Vueアプリ化していく

ここから先のアプリ化では第2回で学んだ「データバインディング」、「リスト」、「ファンクション」の3つを組み合わせながら実装していきます。必要に応じて見返してみてください。

最初はVueのアプリであることを定義してあげる必要があります。HTMLタグのVueアプリ化したい範囲を囲んだdivタグにid属性を指定してアプリケーション名としてappを指定します。

データ表示部分から作成していきましょう。手始めにタイトル部分の情報をJavaScript側にしてみます。重要なのは以下の3ポイントです。

  • new VueでVueインスタンスを作成する
  • Vueインスタンスのdataに表示したいデータを定義する
  • 表示する側では{{ value }}の形式で実装する

もとの”Vue Todo”というタイトルから変更されているかを確認するために”My Vue ToDo”のように異なるタイトル名を定義してみましょう。以下のようなコードになるかと思います。

■DEMO タイトルをデータ定義
(Codepenでは.jsファイル読込エラーがでてしまいますが、気にしないでください)

ここはそんなに難しくないですね。では次はリストの部分のデータをJavaScript側にもたせてみましょう。リスト部分のデータ構造は、リストのタイトル(内容)と終わっているかどうかのフラグと……あとは管理用にIDがあれば十分ですね。なのでその3つのパラメーターを持ったオブジェクトを配列形式で持たせてあげればうまくいきそうです。JavaScriptのオブジェクトは{}、配列は[]のカンマ区切りで記述できます。組み合わせると以下のようになるでしょう。

[
  {
    id: 1,
    title: '靴のムカデ屋でコートを受け取る',
    isDone: true
  },
  {
    id:2,
    title: 'サンジェルマンでカツサンドを買う',
    isDone: false
  },
  {
    id:3,
    title: '爪を切る',
    isDone: false
  },
]

これをdataに持たせ、それをHTML側で表示するようにすればいけます!繰り返しのデータの表示に使うVueの属性は覚えていますか?v-forです!やってみましょう。

■DEMO リストをデータから表示

リストがきれいに表示されていたらOKです!ちなみにここでさらっと新しい属性v-modelを使っています。v-modelはHTMLフォームの一部であるチェックボックスとVueのインスタンスが持つデータを紐付けてくれる要素です。なので、checked属性をつけていなくてもリストの一つ目は表示される時点で既にチェックがつきます。

v-bindでCSS classのオンオフ

この前のHTMLとCSSだけの状態から変わってしまったポイントとして、チェックが入っても取り消し線が引かれないという点があります。これについてはもともとはHTMLのstrikeタグを利用していたからなのですが、strikeタグは固定で取り外しができません。そもそもテキストの装飾はHTMLでやらずにCSSでやるのが鉄則だったはずですよね。ではどうするのかというと、Vueのv-bindclass属性と組み合わせてCSSの設定を切り替えることが出来ます。

まずアプリ専用のCSSを作成しましょう。cssフォルダの配下にstyle.cssを作成してください。

todo
├css
│├milligram.css
│└style.css ★
├js
│└app.js
├lib
│└vue.js
└index.html

作成したらCSSを書いていきます。クラス名はdoneにしてtext-decorationline-throughを設定します。ついでに色も設定してみましょう。

.done {
  text-decoration: line-through;
  color: darkgrey;
}

これでOKです。HTMLでmilligram.cssと同様に読み込むのを忘れないでください。headタグの中にlinkタグで設定しましょう。

次はこれをv-bindを使ってtodoisDoneとCSSクラスのdoneが紐づくようにします。v-bindは略記法があり:(コロン)で書けます。labelタグに下記を追加してみましょう。

:class="{done: todo.isDone}"

では見てみます。

■DEMO スタイルの追加

消してやった感が出ていい感じですね!

Todoの追加機能を作る

それではいよいよ動きのある部分、ToDoの追加機能を実装していきましょう。実装前に何をどうすればいいかイメージすることは大切です。整理してみます。

  1. 入力欄に文字を入力しエンターキーを押す
  2. 文字をベースに新たなtodoオブジェクトを作る
  3. todoオブジェクトをtodosのリストの末尾に追加する

まず1の部分が動くようにしていきます。JSファイルのVueのインスタンスのdataの下にmethodsを追加します。methodsにはaddToDoというファンクションをtitleという引数ありの形で追加しましょう。ひとまずファンクションの中身はアラート表示で引数の内容を表示するように試してみます。dataに新規Todo追加用の変数newTodoTitleを追加します。

var app = new Vue({
  el: '#app',
  data: { 略 }
  methods: {
    addTodo: function(title) {
      alert(title);
    }
  }
})

次にHTMLファイルを修正していきましょう。inputタグを先程作成したnewTodoTitleと紐付けるためv-modelに定義します。HTMLのフォームとVueを紐付けるのは基本的にv-modelです。

v-model="newTodoTitle"

次にinputタグ内でエンターキーを押した際に新たなTodoを追加するようにしたいので、inputタグにキーボードイベントを拾ってくれる属性をつけてやるひつようがあります。ここで登場するのがv-on属性です。v-onはクリックやキー押下をVueインスタンス内のmethodsにあるファンクションに紐付けられます。今回はエンターキー押下時なので、v-on:keyup.enterが属性でそれの値がaddTodo(newTodoTitle)になります。v-bindのようにv-onも略記法があり@(アット)で書けるのでinputタグ内には下記で書いてみます。

@keyup.enter="addTodo(newTodoTitle)"

キー押下なので@keyupです。ボタンやリンクの場合は@clickが使われます。では見てみましょう。

■DEMO メソッドの追加

入力欄にいれた文字がエンター押下時にアラートで表示されますね!これで無事に「入力文字」と「ファンクション」との連携が確認できました。それでは正しく動くように実装していきましょう。先程の2の部分です。

todoオブジェクトは以下のような形になっています。

const newTodo = {
  id: Date.now(), // 時間でID
  title: title,   // 画面で入力した文字列
  isDone: false   // 新規Todoなのでfalse
}

todoオブジェクトを作るにはtitleは入力文字、idは何らかの採番、isDoneは終わったかどうかのフラグなのでデフォルトでfalseで良さそうです。idはサーバーサイドが存在するような規模のアプリであれば色々考慮が必要ですが、今回はフロントだけで完結するようなアプリなのでDate.now()で取得できる1970年1月1日からのミリ秒をそのままIDにしてしまいましょう。DateはJavaScriptにデフォルトで用意されてるオブジェクトです。

ここでは変数を定義する際にconstを利用してます。以前はvarしかありませんでしたが最近のJavaScriptのバージョンアップでブロックスコープのletと定数のconstが追加されました。今後はvarは利用せず、基本的にはconst、変数へ再代入が必要な場合のみletで統一することをおすすめします。ついでにJavaScript 1行目のVueインスタンスもconstに直しておきます。

ではでは作成したtodoオブジェクトをVueインスタンスのtodos配列に追加してあげましょう。配列への追加は、配列に対して.push()メソッドを使います。なので

todos.push(newTodo) // 新しい配列になってしまう……

と思いきやこれでは動きません。これだと新規に空のtodos配列を作りそこに追加するだけです。本来のJavaScriptであれば、Vueインスタンスapp配下のdataの中のtodos配列なので

app.data.todos.push(newTodo) // これでも
this.data.todos.push(newTodo) // こっちでもない

となるかと思いがちですが、そこはVue.jsが裏側で色々やってくれてるので

this.todos.push(newTodo)  // 正解!!

で済んじゃいます。Vue.jsの良いところに、このdatamethodsに対してthisでアクセスできる仕組みが用意されているところです。JavaScriptのthisは解りづらいポイントの一つではありますが、今回はdatamethodsはVueインスタンス内ではthisでアクセスできる、くらいに思っていてください。では確認してみましょう。

■DEMO 追加機能を実装

自分でコーディングしてる方は上のデモ通りに動きますか?Enter押しても追加はされるけど入力欄が残ったままじゃないですか?それはdata内のnewTodoTitleがリセットされてないからです(あえて言いませんでした:P)。thisを使ってリセットしてみてください。

this.newTodoTitle = '';

Todoの削除機能を作る

さて、次は今回最後の機能の実装になります!Todoの削除です。削除の動作イメージは以下の順番ですね。

  1. 完了済みを削除ボタンが押される
  2. datatodosの内、isDonefalsetodoのみの配列deletedTodosを作る
  3. datatododeletedTodosで上書きする

実装できそうですか?2番以外は実は今日やった内容でできるはずです。なので2番だけヒントを出して1番と3番は頑張ってみてください(もちろん最後にデモとコードは用意してます!)。

2番のように、配列で特定の条件に合致したもののみをフィルターしたい時のために、filterというメソッドがJavaScriptの配列には用意されています。filterは引数にcallback関数を与え、その関数は配列の各要素に対して実行されます。実行時にtrueが変えればその要素は新たな配列に渡されます。戻り値は新しい配列なので、新たな変数deletedTodosを用意してやれば良さそうです。

const deletedTodos = this.todos.filter(function(todo) {
  if (todo.isDone === ○○○) return true;
});

○○○に入るのはどっちだと思いますか。終わっていないTodoだけ残したい=isDonefalseのものだけを新たな配列に残したいのでfalseが正解です。1番と3番の実装も問題なくできましたか?正解を見てみましょう。

■DEMO 削除機能を実装

追加と削除を色々試してみてください。複数パターン、チェックなしパターン、全部問題なく動きますね!

次回はローカルストレージとフィルターの実装!

今回はかなり長くなってしまいましたが、アプリ作成の感覚が掴んでいただけたかと思います。しかし!まだこのTodoアプリは終わりではありません。次回は以下を実装していきたいと思います。

  • リロードするとリストが戻ってしまうのを解決!
  • フィルターを動くように実装!

これさえできれば本格的なアプリっぽくなりそうですね!それではまた次回お会いしましょう。TakahiRoyteでした。

TakahiRoyte について

フルスタックエンジニアになりたい一心のSE。今はJavaScriptにハマってます。