こんにちは、TakahiRoyteです!今回はいよいよVue.jsとJavaScriptファイルをToDoアプリに組み込んでいきます。早速コーディング開始です。
JavaScriptファイルを組み込む
まずはディレクトリを準備しましょう。各種ライブラリ用のlib
ディレクトリとJavaScript用の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
タグを使って読み込んでください。
正常に読み込めたかを確認するために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
です!やってみましょう。
リストがきれいに表示されていたらOKです!ちなみにここでさらっと新しい属性v-model
を使っています。v-model
はHTMLフォームの一部であるチェックボックスとVueのインスタンスが持つデータを紐付けてくれる要素です。なので、checked
属性をつけていなくてもリストの一つ目は表示される時点で既にチェックがつきます。
v-bindでCSS classのオンオフ
この前のHTMLとCSSだけの状態から変わってしまったポイントとして、チェックが入っても取り消し線が引かれないという点があります。これについてはもともとはHTMLのstrike
タグを利用していたからなのですが、strike
タグは固定で取り外しができません。そもそもテキストの装飾はHTMLでやらずにCSSでやるのが鉄則だったはずですよね。ではどうするのかというと、Vueのv-bind
をclass
属性と組み合わせてCSSの設定を切り替えることが出来ます。
まずアプリ専用のCSSを作成しましょう。css
フォルダの配下にstyle.css
を作成してください。
todo ├css │├milligram.css │└style.css ★ ├js │└app.js ├lib │└vue.js └index.html
作成したらCSSを書いていきます。クラス名はdone
にしてtext-decoration
でline-through
を設定します。ついでに色も設定してみましょう。
.done { text-decoration: line-through; color: darkgrey; }
これでOKです。HTMLでmilligram.css
と同様に読み込むのを忘れないでください。head
タグの中にlink
タグで設定しましょう。
次はこれをv-bind
を使ってtodo
のisDone
とCSSクラスのdone
が紐づくようにします。v-bind
は略記法があり:(コロン)で書けます。label
タグに下記を追加してみましょう。
:class="{done: todo.isDone}"
では見てみます。
消してやった感が出ていい感じですね!
Todoの追加機能を作る
それではいよいよ動きのある部分、ToDoの追加機能を実装していきましょう。実装前に何をどうすればいいかイメージすることは大切です。整理してみます。
- 入力欄に文字を入力しエンターキーを押す
- 文字をベースに新たなtodoオブジェクトを作る
- 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
が使われます。では見てみましょう。
入力欄にいれた文字がエンター押下時にアラートで表示されますね!これで無事に「入力文字」と「ファンクション」との連携が確認できました。それでは正しく動くように実装していきましょう。先程の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の良いところに、このdata
とmethods
に対してthis
でアクセスできる仕組みが用意されているところです。JavaScriptのthis
は解りづらいポイントの一つではありますが、今回はdata
とmethods
はVueインスタンス内ではthis
でアクセスできる、くらいに思っていてください。では確認してみましょう。
自分でコーディングしてる方は上のデモ通りに動きますか?Enter押しても追加はされるけど入力欄が残ったままじゃないですか?それはdata
内のnewTodoTitle
がリセットされてないからです(あえて言いませんでした:P)。this
を使ってリセットしてみてください。
this.newTodoTitle = '';
Todoの削除機能を作る
さて、次は今回最後の機能の実装になります!Todoの削除です。削除の動作イメージは以下の順番ですね。
- 完了済みを削除ボタンが押される
data
のtodos
の内、isDone
がfalse
のtodo
のみの配列deletedTodos
を作るdata
のtodo
をdeletedTodos
で上書きする
実装できそうですか?2番以外は実は今日やった内容でできるはずです。なので2番だけヒントを出して1番と3番は頑張ってみてください(もちろん最後にデモとコードは用意してます!)。
2番のように、配列で特定の条件に合致したもののみをフィルターしたい時のために、filter
というメソッドがJavaScriptの配列には用意されています。filter
は引数にcallback関数を与え、その関数は配列の各要素に対して実行されます。実行時にtrue
が変えればその要素は新たな配列に渡されます。戻り値は新しい配列なので、新たな変数deletedTodos
を用意してやれば良さそうです。
const deletedTodos = this.todos.filter(function(todo) { if (todo.isDone === ○○○) return true; });
○○○に入るのはどっちだと思いますか。終わっていないTodoだけ残したい=isDone
がfalse
のものだけを新たな配列に残したいのでfalse
が正解です。1番と3番の実装も問題なくできましたか?正解を見てみましょう。
追加と削除を色々試してみてください。複数パターン、チェックなしパターン、全部問題なく動きますね!
次回はローカルストレージとフィルターの実装!
今回はかなり長くなってしまいましたが、アプリ作成の感覚が掴んでいただけたかと思います。しかし!まだこのTodoアプリは終わりではありません。次回は以下を実装していきたいと思います。
- リロードするとリストが戻ってしまうのを解決!
- フィルターを動くように実装!
これさえできれば本格的なアプリっぽくなりそうですね!それではまた次回お会いしましょう。TakahiRoyteでした。
記事一覧
第1回 JSの歴史とVue.jsを選んだ理由
第2回 開発環境とHello Vue.js
第3回 構造のHTMLとスタイルのCSS
第4回 JSコーディング開始
第5回 保存と読込 ★次回★
第6回 リストのフィルター