yuheijotaki.com

Vue.js で クイズ実装

f:id:jotaki:20190212100544p:plain

設問 + 答え のクイズをVue.jsで実装する。

URL

GitHub pages:https://yuheijotaki.github.io/practice-exam/
GitHub リポジトリ:https://github.com/yuheijotaki/practice-exam

機能

  • 設問/正解などのデータは JSON にいれて Vue で描画
  • 設問に対してユーザーが選択式で解答する
  • 「答え合わせ」ボタン押下で、正解の表示、正誤判定

JSON

https://yuheijotaki.github.io/practice-exam/static/assets/qa.json

  • ID id
  • 設問種別(カテゴリー) field
  • 解答タイプ ansType
    • 単一方式: single (ラジオボタン)
    • 複数選択方式: multi (チェックボックス)
  • 設問テキスト queText
  • 解答 ansChoice
    • "a": "選択肢aです。"
  • 正解 ansItem
    • 単一: ["a"]
    • 複数: ["a","b"]
  • 解説 ansComment
  • 出典元 ansSource

ハマった箇所

いろいろハマった気がしますが大きくはふたつです

フォームバインディングに v-mdoel: が使えない

JSON から取得した設問リストをもとに解答のラジオボタン/チェックボックスを動的する場合、v-model: が使えず、自力で選択されたか否かを判定してデータに格納する必要があるっぽい。
ラジオボタンは値を上書きすればいいだけなのでまだよかったが、チェックボックスは v-on:change を使うとチェック毎に値が溜まっていく一方なので、溜まった値が奇数の場合は true 、偶数の場合は false みたいに、おそらくよくないやり方をしてしまった。

答え合わせ時に正解と解答が一致しない

これも探り探りやりましたが、正解と解答は別の配列で作っていて、それをマッチングさせるようにしているが、 正解:["a"] と解答: ["a"]=== で繋いでも true にならなかったので、一度配列たちを toString() して判定した。

課題

  • 正解数/正誤率の表示(カテゴリー毎に正誤率を計算できるとなお良い)
  • バリデーション
    • チェックボックスの上限設定(これはなくてもOKかな)
    • 「答え合わせ」ボタンを押した際に未入力の問題がないか
  • 見た目の調整
  • リファクタリング(命名/コンポーネント化)

感想

  • JSのオブジェクトについて少し理解が深まった(難しさも分かった..)
  • やっぱり足りていないのはJSの基礎力かな..
  • どんなコードでも形になったのでとりあえずよしとします

結構時間かかってしまったので、次のはもう少しレベル落とそうかなと思います

参考にしたリンク

JavaScript

オブジェクトのループ
https://qiita.com/ledsun/items/953b25b60592c22811ca
https://chaika.hatenablog.com/entry/2018/10/15/090000

オブジェクトのプロパティへのアクセス
https://qiita.com/tomcky/items/0757348473873765432e

オブジェクトのプロパティ削除
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Creating_New_Objects/Deleting_Properties

奇数・偶数の判定
https://9-bb.com/javascript/

型変換いろいろ
https://qiita.com/zawascript/items/a25eaf7a222ac3671275

Vue.js

computedmethods の違い、組み合わせ方法など
https://dev83.com/vue-computed-methods/

フォーム要素のバインディングに v-model を使わない方法
https://qiita.com/gyarasu/items/7bc16ec3466f00b2c9fa

オブジェクトに動的に値を追加してリアクティブにする方法
https://qiita.com/tmak_tsukamoto/items/7623f458448fa7cd01c7