vue-quiz の Tips

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"
>