В этой статье мы создадим простое веб-приложение для викторин. Это будет сделано на Vue.js.

Это будет простой формат флеш-карты. У карты будет вопрос и несколько вариантов. Если выбранный вариант является правильным ответом, карточка перевернется и поздравит нас. Для этого эффекта мы будем использовать некоторые эффекты перехода. Конечный результат будет выглядеть так.

Во-первых, давайте настроим наши файлы. Откройте свой терминал, перейдите в папку проекта и введите в терминале следующие команды. Вы можете выбрать любое название для своего проекта. Вам не понадобятся Vuex или Vue-router, поэтому не выбирайте их. Остальные варианты на ваше усмотрение, вы можете выбрать те, которые хотите.

Наши исходные файлы готовы. Откройте ваш любимый редактор кода / IDE и приступим.

Из стандартного кода удалите компонент HelloWorld.vue, поскольку он нам не понадобится. Одним из основных компонентов будет компонент App.vue. Викторины на основе карточек имеют очень простую структуру. Есть вопрос с несколькими вариантами (обычно 4) с одной стороны и ответом с другой. Таким образом, мы можем поместить наши вопросы с параметрами в отдельный компонент под названием Question.vue и поместить ответ в отдельный компонент под названием, как вы уже догадались, Answer.vue.

Начнем с App.vue и настроим базовую структуру нашего приложения. В этом проекте я буду использовать Bootstrap v4. Вы можете использовать его или любую другую библиотеку, с которой вы знакомы.

У нас есть заголовок Самая крутая викторина. Затем есть тег <transition> с некоторыми атрибутами. Если вы не знакомы с тегом transition, это то, что нам предоставляет Vue. Это позволяет нам применять переходы к чему угодно, просто заключив элемент в тег <transition>. У нашего тега два атрибута: name - это имя перехода, а mode="out-in" сообщает Vue дождаться полного завершения предыдущего перехода, прежде чем начинать новый.

Внутри у нас есть еще один предоставленный Vue тег под названием <component>. Это используется для динамических компонентов.

Базовая структура будет такой - у нас есть динамический компонент, который изначально всегда будет настроен на отображение Question компонента. Когда мы выберем правильный ответ среди вариантов, он переключит компонент на Answer. Это возможно с динамическими компонентами. И мы можем применять переходы при переключении между компонентами благодаря тегу <transition>.

Что касается атрибутов нашего тега <component>. Последние два v-on мы используем для настраиваемых событий. @answered будет настраиваемым событием, созданным компонентом Question. Он покажет нам, был ли выбран правильный ответ. Затем мы можем выбрать, что делать. @confirmed - это тот, который прикреплен к компоненту Answer. Он снова переключается на компонент Question и показывает новый вопрос.

Первый атрибут :is необходим для переключения между динамическими компонентами. Это сам по себе динамический атрибут, так как ему нужно будет изменить его значение.

Остальной код в шаблоне - это просто Bootstrap, используемый для добавления визуального совершенства к странице, чтобы она не выглядела как что-то из первых дней Интернета.

Теперь перейдем к основной логике этого компонента. Он довольно маленький (хотя и не такой маленький, как логика для Answer).

Сначала мы импортируем два компонента, которые создадим. Я поместил их в отдельную папку /components.

У нас есть только один атрибут данных, который будет использоваться для динамического переключения между обоими компонентами. Единственный метод используется для выполнения определенного действия в зависимости от того, был ли выбран правильный вариант.

Обратите внимание, что мы не решаем, был ли выбран правильный ответ. Это делается с помощью компонента Question. Мы просто действуем в соответствии с этим. Если компонент Question говорит, что был выбран правильный ответ, мы переключаемся на компонент Answer, и если он был неправильным, мы показываем предупреждение.

Теперь, когда шаблон и основная логика готовы, давайте быстро закончим эффекты перехода.

Классы .flip-enter-active и .flip-leave-active также предоставляются Vue, когда мы дали переходу имя (Vue действительно дает нам так много хороших вещей). Первый класс используется, когда переход находится на стадии входа, что означает его начало. Второй класс применяется, когда переход активно завершается или завершается.

Лучше вам увидеть @keyframes в действии, чем мне объяснять это. Имеет такой эффект

Компонент Answer не содержит большого количества кода, поскольку все, что он делает, показывает поздравительное сообщение.

Шаблон довольно прост для понимания. Просто <h1> и кнопка, отображающая следующий вопрос.

Метод вызывается нажатием кнопки и генерирует событие подтверждено для родительского App.vue компонента. Если вы помните, когда это событие генерируется, компонент App переключается на компонент Question.

Теперь о последнем и, вероятно, самом длинном из трех компонентов. Компонент Question имеет больше логики, чем предыдущие компоненты, поскольку он выполняет важную задачу создания новых вопросов и определения того, был ли выбран правильный ответ.

Кажется подавляющим, но на самом деле это не так. Основная его часть - это Bootstrap. Этот шаблон отображает карточку (доступную в Bootstrap v4) с простым вопросом на сложение или вычитание. Числа случайны, и мы также рандомизировали операцию (она будет случайным образом выбирать между сложением и вычитанием).

Далее у нас 4 кнопки. Это будут наши варианты ответа на вопрос. Один из них будет правильным ответом (кстати, положение правильного ответа тоже меняется случайным образом). Довольно много случайности 😉. Но вот что делает это забавным!

После понимания остальной части кода станет ясно, что делает интерполированная строка.

У нас есть две переменные, чтобы указать режим работы. btnData - это массив объектов. Каждый объект представляет собой ответ. У него два свойства: ответ - это ответ, который представляет кнопка. На каждую кнопку будет дан ответ, который может быть правильным, а может и нет. Это свойство будет содержать это. Правильно сообщит нам, верен этот ответ или нет.

Даже если для свойства правильно первого объекта установлено значение true, оно будет изменено позже.

Свойство данных question по умолчанию будет иметь строку. Итак, если наш метод, который генерирует вопрос, почему-то не работает, мы будем знать, что что-то не так.

Затем у нас есть этот created() крючок жизненного цикла. Когда этот компонент будет создан, будет выполнен метод generateQuestion(). Как и ожидалось, этот метод отвечает за создание нового вопроса, а также за назначение правильного ответа одной из четырех кнопок.

Довольно долгая работа, но не волнуйтесь, мы пройдем через это вместе.

Прежде всего, у нас есть 3 переменные. Есть переменные firstNumber и secondNumber, которые будут иметь случайное число от 1 до 100. Третья переменная modeNumber будет представлять режим работы. Еще есть загадочная generateRandomNumber() функция. Что это значит? Он генерирует для нас случайное число, но с немного другой логикой. Посмотрим на это после этой функции.

Затем у нас есть еще одна переменная, которая, вероятно, самая важная - correctAnswer. Это будет содержать правильный ответ на наш вопрос. Обязательно используйте let, а не const, поскольку нам нужно переназначить его.

После объявления наших переменных у нас есть switch case. Он проверит modeNumber, который мы случайно выбрали между 1 и 2. Причина этого - наши самые первые объявления переменных, в которых мы присвоили номер нашим режимам работы. Теперь это пригодится.

Мы легко можем изменить нашу логику в зависимости от случайно выбранной операции. Если бы случайное число было 1, мы бы добавили переменные firstNumber и secondNumber и поместили бы это как правильный ответ. Если бы было 2, мы бы вычли их. Затем мы назначаем соответствующую строку свойству данных question.

Наш вопрос готов и у нас есть правильный ответ на него. Затем мы случайным образом назначаем его кнопке. Следующая часть может показаться запутанной, но на самом деле это не так.

У каждой кнопки для свойства правильно установлено значение false. Свойству answer будет присвоено случайное число. Но мы не можем просто присвоить полностью случайное число. Например, если вопрос был Что такое 2 + 3?, у нас не может быть варианта с ответом 573. Очевидно, это был бы неправильный ответ. Таким образом, наши варианты должны быть случайными, но все же в пределах определенного диапазона. Мы используем функцию generateRandomNumber() и передаем минимальное число, которое на 10 меньше правильного ответа, и максимальное число, которое на 10 больше правильного ответа.

Похоже, хорошее решение, не правда ли. Но функции передается третий аргумент, что он делает?

Я рада, что вы спросили. Теперь мы не хотим, чтобы наш случайный вариант был фактическим ответом, не так ли? Таким образом, третий аргумент указывает функции сгенерировать случайное число в переданном нами диапазоне, но это не должен быть фактический ответ. Таким образом, все кнопки имеют неправильный ответ.

Теперь мы генерируем случайную позицию индекса. Затем мы назначаем правильный ответ кнопке в этом индексе и устанавливаем для ее свойства правильно значение true.

Короче говоря, мы дали всем кнопкам случайные варианты и заявили, что они неправильные. Затем выбрал случайную кнопку, дал ей правильный ответ и объявил, что это правильный.

Но почему мы так сделали? Разве мы не выбрали случайную кнопку, назначили ей ответ и затем начали назначать неправильные ответы остальным кнопкам? Конечно, могли.

Но потом, назначая неправильные ответы всем кнопкам кроме правильного, который выбирается случайным образом ?! Какая боль. Хоть как-то можно, а я ленивый.

Для остальных функций:

Как я уже говорил о функции generateRandomNumber(), она принимает 3 аргумента. Первые два - это диапазон, в котором должно быть сгенерировано случайное число. Третий аргумент используется только тогда, когда мы убеждаемся, что сгенерированное случайное число не является правильным ответом. Если он совпадает с correctAnswer, функция будет выполняться рекурсивно, пока мы не получим другое число.

Обработчик кликов onAnswer генерирует событие answered и передает родительскому (App.vue) компоненту, был ли ответ правильным или нет.

На этом наше приложение готово. Запустите сервер разработки, чтобы увидеть свой код в действии.

Вот репозиторий GitHub кода для справки. Надеюсь, вам понравилось это делать. Я хотел бы, чтобы вы изменили и улучшили его. С нетерпением ждем вашего ответа в разделе комментариев ниже.

Это приложение взято из Курса Vue на Udemy, написанного Максимилианом Шварцмюллером. Он учит множеству удивительных вещей о Vue, и вы наверняка найдете что-то ценное в этом курсе. Так что обязательно проверьте это.

Я сейчас прохожу его курс и считаю его ценным. Это не спонсорский пост, а личная рекомендация.

Первоначально опубликовано на dev.to.