yuheijotaki.com

vue-quiz の Tips

f:id:jotaki:20190212100544p:plain

vue-quiz を作った際にでてきたTipsをまとめておきます

同じID(値)を持った配列をまとめたい

今回の場合、ラジオボタン式(単一解答)なら問題ないけど、チェックボックス式(複数解答)のときに整形する必要がでてきた
つまり

array = [
  { id: "1", answer: "d" },
  { id: "3", answer: "a" },
  { id: "3", answer: "b" },
  { id: "3", answer: "c" },
  { id: "4", answer: "b" }
]

を↓のようにしたい

formatArray = [
  { id: "1", answer: ["d"] },
  { id: "3", answer: ["a","b","c"] }
  { id: "4", answer: ["b"] }
]

こういうときに reduce() を使うみたい

const data = array.reduce((acc, value) => {
  acc[value.id] = acc[value.id] ? acc[value.id] : [];
  acc[value.id] ? acc[value.id].push(value.answer) : [value.answer];
  return acc;
}, {});
let formattedAnswerArray = Object.entries(data).map(d => ({ id: d[0], answer: d[1] }) );

参考: https://stackoverflow.com/questions/31688459/group-array-items-using-object

配列の比較

これも参考のとおりなのですが、配列を比較、今回の場合は答え合わせの際に、問題の正解とユーザーの解答を比べるときに使いました。

function array_equal(a, b) {
  if (!Array.isArray(a))    return false;
  if (!Array.isArray(b))    return false;
  if (a.length != b.length) return false;
  for (var i = 0, n = a.length; i < n; ++i) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}

というfunctionを作って computed

// スコアの計算
calcScore: function () {
  const correctAnswer = this.correctAnswerArray; // 問題の正解
  const userAnswer = this.userAnswerArray;       // ユーザーの解答
  let userScore = 0;
  correctAnswer.forEach((value,index) => {
    const correctAnswerValue = value;
    const userAnswerValue = userAnswer[index];
    // ユーザーの解答が問題の正解とイコールならスコアを+1する
    if ( array_equal(correctAnswerValue,userAnswerValue) ) {
      userScore ++;
    }
  });
  return userScore;
}
<template>
...
  <p>{{calcScore}}問正解です</p>
...
</template>

参考: https://marycore.jp/prog/js/array-equal/

<template> を使って条件分岐

直接HTMLタグに分岐を書かずに <template> に分岐を書く。
あらかじめどちらに統一すると決めてマークアップしていったほうがいいですね。
answerCorrect() メソッドで分岐する場合

<div>
  <template v-if="answerCorrect(hoge,fuga)">
    <p class="text text--correct">{{ value }}</p>
  </template>
  <template v-else>
    <p class="text">{{ value }}</p>
  </template>
</div>

カスタムデータ属性(data-*)をバインドする

<input
  type="checkbox"
  v-bind:data-hoge="post.id"
  >