Данные Vue недоступны до вызова JSON.stringify().

Я не уверен, как решить эту проблему, потому что в ней есть много общего, и такое поведение я никогда не видел ни в JavaScript, ни в Vue.js. Конечно, я постараюсь сделать код минимальным для большинства критические и кусочки

Я использую vue-class-component(6.3.2), поэтому мои компоненты Vue(2.5.17) выглядят как классы:) Этот конкретный компонент выглядит так:

import GameInterface from '@/GameInterface';

class GameComponent extends Vue {
  public gameInterface = GameInterface();
  public mounted() {
    this.gameInterface.launch();
  }
}

GameInterface возвращает объект с методом запуска и другими игровыми переменными.

В файле интерфейса игры метод выглядит примерно так:

const GameInterface = function () {
  const obj = {
    gameState: {
      players: {},
    },
    gameInitialized: false,
    launch() => {
      game = createMyGame(obj); // set gameInitialized to true
    },
  };
  return obj;
}
export default GameInterface;

Отлично, это работает, объект передается в мою игру Phaser:), и он также возвращается методом, что означает, что теперь Vue может использовать этот объект.

В какой-то момент у меня есть метод получения в моем классе Vue, который выглядит так:

get currentPlayer() {
  if (!this.gameInterface.gameInitialized) return null;

  if (!this.gameInterface.gameState.players[this.user.id]) {
    return null;
  }
  return this.gameInterface.gameState.players[this.user.id];
}

И, конечно же, возвращается ноль, даже если игрок и идентификатор явно присутствуют. Когда я console.log this.user.id я получил 4, а также gameInterface.gameState.players возвращает объект с геттерами для игроков следующим образом:

{
  4: { ... },
  5: { ... },
}

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

Но я нашел очень странный способ "исправить" эту проблему: добавив JSON.parse(JSON.stringify(gameState)) вот так

get currentPlayer() {
  // ...
  if (!this.gameInterface.gameState.players[this.user.id]) {
    // add this line
    JSON.stringify(this.gameInterface.gameState);
    return null;
  }
  return this.gameInterface.gameState.players[this.user.id];
}

Он успешно возвращает текущего игрока для нас... Странно нет?

Я предполагаю, что когда мы делаем это, мы "ударяем" объект, Vue замечает некоторые изменения из-за этого и корректно обновляет объект. Кто-нибудь знает, что мне здесь не хватает?

1 ответ

Поработав над проблемой с другом, я обнаружил, что основной проблемой является специфичная для JavaScript проблема, связанная с реактивной природой Vue.

https://vuejs.org/v2/guide/reactivity.html
В этом разделе документации обсуждается предостережение об обнаружении изменений Vue:

Vue не может обнаружить добавление или удаление свойства. Поскольку Vue выполняет процесс преобразования getter/setter во время инициализации экземпляра, в объекте данных должно присутствовать свойство, чтобы Vue смог преобразовать его и сделать его реактивным.

Когда во время игры я настраивал игроков так:

gameObj.gameState.players[user.id] = {...playerData}

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

Чтобы правильно установить нового игрока, я решил использовать оператор распространения, чтобы изменить players объект, на который реагирует Vue, и, в свою очередь, Vue обнаружит добавление моего игрока следующим образом:

gameObj.gameState.players = {
  ...gameObj.gameState.players,
  [user.id]: {...playerData}
}

Vue также обсуждает другой метод, называемый $set, который вы можете прочитать на той же странице.

Другие вопросы по тегам