Это вторая статья в моей серии руководств, в которой я пытаюсь объяснить концепции Vue.js, воссоздав боевую сцену из Pokemon.

Исходное руководство
# 1 Однофайловые компоненты
# 2 Атаки: $ refs, Promises и шина событий
# 3 Vuex: управление состоянием
# 4 Расчет повреждений
# 5 Переходы и анимация

Во второй части мы вернем функции атаки.

Есть несколько способов сделать это.

  1. Взломайте его вместе с $ refs и Promises
  2. Используйте шину событий, которая делает тяжелую работу
  3. Разделите логику / данные дальше с помощью Vuex, библиотеки управления состоянием.

В этой статье мы рассмотрим первые два варианта, поскольку их несложно объяснить и реализовать.

Давайте приступим.

Функции атаки

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

Откройте Pokemon.vue, мы собираемся добавить методы attack () и pickRandomAttack ().

Давайте определим их во вновь созданном свойстве методов:

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

Небольшое примечание. Мы получаем доступ к родительскому состоянию компонента pokemon через this. $ parent. Как вы можете догадаться, он возвращает экземпляр Vue компонента, на который ссылается компонент pokemon. В нашем сценарии мы уверены, что App.vue всегда будет родительским, поэтому его можно использовать . В другом сценарии вы не уверены, что вам нужно найти способ обойти это (с помощью событий или менеджера состояния).

Подход, основанный на обещаниях

Если вы не знаете о обещаниях, вы можете быстро ознакомиться с вариантом использования и API здесь.

По сути, промисы позволяют нам четко определить цепочку команд.
Он начинается с определения функции, которая может либо пройти, либо потерпеть неудачу, с помощью then () мы можем определить, что произойдет, когда она будет успешно разрешена. . С помощью catch () вы можете определить, что должно произойти в случае сбоя.

Опишем нашу цепочку подчинения.

Когда пользователь выбирает атаку:

  1. Снижаем HP соперника
  2. Подождите секунду, пока не опустится полоса HP.
  3. Если противник жив, выберите случайную атаку и уменьшите HP игрока.
  4. подождите секунду, пока упадет полоса HP

После шагов 1 и 3 мы также обновим текст битвы, добавив что-то вроде «{pokemon} used {attack}».

В начале шага 3 и в конце шага 4 мы проверим, достаточно ли осталось HP, в противном случае мы не выполним обещание и покажем, что покемон потерял сознание.

После успеха нам придется изменить текст битвы на «Что будет делать {pokemon.player.name}?».

Давайте превратим этот процесс в разрешение обещания:

  • Обещание: атаковать покемонов противника
  • Ошибка при (отклонить): HP оппонента упадет до 0
  • Успешно на (разрешении): у противника осталось HP
  • При успехе (затем): вернуть новое обещание, которое выбирает случайную атаку от противника и использует ее на игроке.
  • Ошибка при (отклонить): HP игрока упадет до 0
  • Успешно на (разрешении): у игрока осталось HP
  • При успехе (затем): сбросить текст битвы
  • при неудаче (catch): изменить текст битвы и показать меню endOptions

Давайте добавим это в код, откроем App.vue и добавим этот код в метод resetBattle:

Конструктор

Как видите, вы создаете обещание, назначая функцию в его конструкторе. Этой функции назначаются 2 параметра: обратный вызов разрешения и обратный вызов отклонения. Как вы правильно догадались, вы должны называть их одним успехом / неудачей.

Вы помните из прошлого урока, что мы добавили атрибут ref к компонентам покемонов?

Благодаря этому мы можем получить доступ к его состоянию и методам через this. $ Refs с присвоенным именем.

Нам необходимо настроить функцию атаки так, чтобы она также принимала в качестве параметров обратные вызовы resolve и reject.

тогда

Первый будет вызван, если у противника все еще осталось HP.
В этом случае выбирается случайная атака на покемона игрока.

Мы делаем это, возвращая другое обещание (поскольку предыдущее обещание уже выполнено).

тогда

Второй затем вызывается, если у покемона игрока все еще осталось HP.

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

поймать

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

Приятно знать, что если обещание отклоняется, когда игрок атакует, оно не достигает нового обещания оппонента.

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

Вернемся к Pokemon.vue и добавим обратные вызовы resolve / reject:

Вот и все обещания, атаки работают.

Вы можете найти копию кода прямо здесь:



Событийный подход

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

Основное отличие подхода, основанного на обещаниях, заключается в том, что каждое событие имеет собственное имя, поэтому код будет легче читать и понимать.

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

Начнем с того, что потянем внутрь.

Как только это будет сделано, нам нужно будет добавить его в наш main.js сразу после загрузки Vue.js.

События

Давайте посмотрим на более традиционный подход Javascript.

Мы хотим использовать 4 события:

  • player.attack (attackName): выполняет атаку покемона игрока.
  • Оппонент.attack (): выполняет атаку покемона оппонента.
  • attack.completed (): сбрасывает текст битвы.
  • обморок (pokemonName): изменяет текст битвы и показывает endOptions

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

Вы можете определить его в определении экземпляра Vue, я обычно помещаю его сразу после любых определений данных (после метода данных и вычисляемого свойства).

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

Однако он читается более четко, он имеет логичное название и порядок.

Выполнение

Давайте заменим реализацию на основе обещаний нашей реализацией на основе событий, изменив метод processAttack на следующее:

Это так просто: нам не нужно больше одной строчки кода, осталось только переписать функцию атаки.

Нам просто нужно заменить места, где мы ранее использовали обратные вызовы resolve и reject.

Давайте откроем Pokemon.vue и соответствующим образом изменим метод атаки:

Вот и все, вот как вы могли бы использовать события вместо обещаний.

Вы можете найти код этого подхода прямо здесь:



В следующий раз мы рассмотрим возможность использования Vuex, чтобы упростить управление состоянием, чтобы мы могли начать подготовку к реализации более сложной логики, которая на самом деле не принадлежит компонентам.

Как всегда, вы можете получить самый последний код на github:
https://github.com/happyDemon/learning-vue-through-pokemon