Vue.jsの続きです。前回はcomputed(算出プロパティ)で割り勘アプリを作りました。今回はwatch(監視プロパティ)で簡単なクイズを作ってみます。それではいきましょう!
【目次】
※参考:【Vue.js】computed(算出プロパティ)で割り勘アプリを作る(おまけでこち亀アプリも) - クモのようにコツコツと
戦国時代クイズを作った
watch
は「監視プロパティ」と言って、何かを監視して、変化があったら処理を実行する。これを使うと、例えばこちらのような簡単なクイズを作れる。
See the Pen vue watch01 by イイダリョウ (@i_ryo) on CodePen.
クイズの答えを入力すると、正解するまでは「不正解!」というアラートが出続ける。(正解は後述します)
以前の記事でフォームに入力した内容をリアルタイムに表示した。
※参考:【Vue.js】v-modelデータバインディング事始め(リンダリンダの歌詞を変えてオリジナルラブソングを作る) - クモのようにコツコツと
今回は入力内容によって処理内容を分岐している。これを実現するのがwatch
。
v-model.lazyでフォーカスアウト後に処理を実行(HTML)
コードを見ていく。まずはHTML。
<section id="quiz"> <h2>戦国時代クイズ</h2> <p>龍造寺四天王の一人で主君・龍造寺隆信から「百人並みの武勇を有する」と賞され、それにちなんだ姓を賜った武将の名前は?</p> <input v-model.lazy="input" placeholder="武将名"></input> </section>
input
要素の中にv-model.lazy
属性がある。このlazy
は「修飾子」といって、フォームをフォーカスアウトした時(またはエンターを押したとき)に処理を実行する。(これがないと一時文字を打つごとにイベントが発火した)
修飾子は他にこんなものもある。
修飾子 | 詳細 |
---|---|
lazy | 全部書き終わってから実行 |
number | 値を自動的に数値に変換 |
trim | 空白を自動的に削除 |
どれもフォーム入力に使えそう!
watch以外のVue設定
次はJSのコード。
new Vue({ el: '#quiz', data: { answer: '百武賢兼', input: '' }, watch: { input: function () { const judgment = this.input.indexOf(this.answer); if (judgment >= 0) { alert('「'+ this.answer +'」正解!あなたは戦国通!!'); } else { alert('「'+ this.input +'」不正解!もう一回挑戦。') } } } });
入れ子が多いので順番に説明する。
まず全体を囲っているのがVueインスタンス。
new Vue( //処理 );
引数には連想配列が入っている。
new Vue({ el: //値, data: //値, watch: //値 });
キー名はel
、data
そして今回のテーマwatch
。
el
キーの値は #quiz
new Vue({ el: '#quiz', data: //値, watch: //値 });
これでHTMLの#quiz
と紐づく。
data
の値は連想配列。キーはanswer
とinput
。
new Vue({ el: '#quiz', data: { answer: //値 input: //値 }, watch: //値 });
answer
キーの値に答え「百武賢兼」が入っている。input
キーはHTMLのv-model
で中身は空。(ここに何か入れると初期値になる)
new Vue({ el: '#quiz', data: { answer: '百武賢兼', input: '' }, watch: //値 });
watchのJS設定
次はいよいよwatch
の設定。ここだけ抜粋。watch
キーの値は連想配列で、中はinput
キー。
watch: { input: //処理 }
input
キーの値は無名関数。
watch: { input: function () { //処理 } }
まず変数judgment
を設定
watch: { input: function () { const judgment = this.input.indexOf(this.answer); //処理 } }
input
の入力値にanswer
が含まれているかをindexOf()
で判定する。indexOf()
は0
からのカウントで何文字目にあるかを返す。ない場合は-1
を返す。
※参考:indexOfメソッド - Stringクラス - JavaScript入門
if文の条件をjudgment
が0
より多い(正解)か、にする。else
には不正解のときの処理を書く
watch: { input: function () { const judgment = this.input.indexOf(this.answer); if (judgment >= 0) { //正解の値があった場合の処理 } else { //正解の値がなかった場合の処理 } } }
最後、正解、不正解の処理を書く。
watch: { input: function () { const judgment = this.input.indexOf(this.answer); if (judgment >= 0) { alert('「'+ this.answer +'」正解!あなたは戦国通!!'); } else { alert('「'+ this.input +'」不正解!もう一回挑戦。') } } }
アラートを出す。正解時はthis.answer
で答えを表記。不正解時はthis.input
でフォームの入力値を表示。
で、こうなった。
See the Pen vue watch01 by イイダリョウ (@i_ryo) on CodePen.
正解を入れるとこうなる。
「百武」という姓は「百人並みの武勇」から来ているんですな。
※参考:2019/11/12追記
下記のコメントをいただきました。(Watchを使わないで実装する方法)
戦国時代クイズに関しては、watchを使用せずとも実装できそうです。
v-model.lazy -> @change
watch -> methodsカウントダウンタイマーを監視してタイマーが0になったら処理を実行するなど こういった内容は確かにwatchでないと厳しのかなと思います...
最後に
ということで、watch
でインプットの値を監視して、簡単なクイズを作りましたー。
watch
はフォームのバリデーションなんかにも使えそう!他にもカーソルの動きを監視したり、カウントダウンタイマーを監視してタイマーが0になったら処理を実行するなど、いろいろな使い道があるようです。
さて次回はVue.jsのアニメーションtransition
というのをやってみる予定。それではまた!
※参考:Vue.jsの習得のためにやったことまとめ
qiita.com