function shuffle(arr) {
for (let i = arr.length; i > 1;) {
const j = Math.random() * (i--) | 0;
[ arr[i], arr[j] ] = [ arr[j], arr[i] ];
}
return arr;
}
computed: {
shuffledAnswers() {
return shuffle(Object.entries(this.questions[this.idx].answers));
},
...
<div v-for="[ key, answer ] in shuffledAnswers">
...
UPD. Конечно, вопрос был не об этом, но есть ряд замечаний по поводу показанного кода.
"answers": {
Пусть это будет массив. Соответственно, правильный ответ будет обозначаться через индекс.
import usersData from "../questions.json";
Не надо импортировать вопросы в компоненте теста, пусть они передаются в него через props.
selectedAnswer: "",
Всего один? Этого мало, надо запоминать все полученные ответы.
count: 5,
<div v-if="idx < count">
Если завтра добавятся новые вопросы или удалятся какие-то из существующих, побежите изменять значение этого свойства? Оно не нужно, надо смотреть на длину массива с вопросами. Или, можно сделать вычисляемое свойство, представляющее текущий вопрос (просто извлекаем элемент из массива с вопросами по индексу текущего вопроса), и проверять, существует ли он.
computed:{
randomQuestions () {
usersData.sort(() => Math.random() - 0.5)
Во-первых, вычисляемые свойства не должны изменять данные. Во-вторых,
почему не надо так сортировать. Поскольку массив вопросов никак не изменяется, делать тут вычисляемое свойство смысла нет, пусть оно будет обычным. Перемешанная копия массива с вопросами, у вопросов перемешанные массивы ответов, а также добавлено свойство под ответ, выбранный пользователем.
:disabled="selectedAnswer != ''"
Блокировать выбор ответа не надо - вдруг пользователь случайно не туда нажал. Пусть будет возможность изменить сделанный выбор. Это касается не только ответов на текущий вопрос, а всех, т.е., в дополнение к
<button
@click="nextQuestion"
надо сделать такую же кнопку для перехода к предыдущему вопросу.
document.querySelectorAll("input").forEach((el) => (el.checked = false));
Не надо лезть в DOM руками. Чтобы при переходе к следующему вопросу сбрасывать выбор, достаточно пересоздавать элементы, назначив их общему предку ключ, зависящий от индекса (
:key="индекс_вопроса"
). Но это, конечно, костыльное решение. Правильно будет управлять радиокнопками основываясь на данных, через
v-model
.
@change="answered($event)"
answered(e) {
this.selectedAnswer = e.target.value;
if (this.selectedAnswer == this.questions[this.idx].correctAnswer) {
this.correctAnswers++;
Никаких событий слушать не надо, оформляем подсчёт результатов в виде вычисляемого свойства.
https://jsfiddle.net/0L9ayx1u/1/