クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【Vue.js】watch(監視プロパティ)で戦国時代クイズを作った

Vue.jsの続きです。前回はcomputed(算出プロパティ)で割り勘アプリを作りました。今回はwatch(監視プロパティ)で簡単なクイズを作ってみます。それではいきましょう!

【目次】

※参考:【Vue.js】computed(算出プロパティ)で割り勘アプリを作る(おまけでこち亀アプリも) - クモのようにコツコツと

戦国時代クイズを作った

watchは「監視プロパティ」と言って、何かを監視して、変化があったら処理を実行する。これを使うと、例えばこちらのような簡単なクイズを作れる。

See the Pen vue watch01 by イイダリョウ (@i_ryo) on CodePen.

クイズの答えを入力すると、正解するまでは「不正解!」というアラートが出続ける。(正解は後述します)

f:id:idr_zz:20190709002727j:plain

以前の記事でフォームに入力した内容をリアルタイムに表示した。

※参考:【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: //値
});

キー名はeldataそして今回のテーマwatch

elキーの値は #quiz

new Vue({
  el: '#quiz',
   data: //値,
   watch: //値
});

これでHTMLの#quizと紐づく。

dataの値は連想配列。キーはanswerinput

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文の条件をjudgment0より多い(正解)か、にする。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.

正解を入れるとこうなる。

f:id:idr_zz:20190709002850j:plain

「百武」という姓は「百人並みの武勇」から来ているんですな。

※参考:2019/11/12追記
下記のコメントをいただきました。(Watchを使わないで実装する方法)

戦国時代クイズに関しては、watchを使用せずとも実装できそうです。

v-model.lazy -> @change
watch -> methods

カウントダウンタイマーを監視してタイマーが0になったら処理を実行するなど こういった内容は確かにwatchでないと厳しのかなと思います...

最後に

ということで、watchでインプットの値を監視して、簡単なクイズを作りましたー。

f:id:idr_zz:20190709001255j:plain

watchはフォームのバリデーションなんかにも使えそう!他にもカーソルの動きを監視したり、カウントダウンタイマーを監視してタイマーが0になったら処理を実行するなど、いろいろな使い道があるようです。

さて次回はVue.jsのアニメーションtransitionというのをやってみる予定。それではまた!


※参考:Vue.jsの習得のためにやったことまとめ
qiita.com