Данные Vue недоступны до вызова JSON.stringify (). - PullRequest
0 голосов
/ 23 января 2019

Я не уверен, как решить эту проблему, потому что в ней есть немало проблем, и такое поведение я никогда не видел ни в 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: { ... },
}

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

Но я нашел очень странный способ "FIX" этой проблемы: добавив 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 Ответ

0 голосов
/ 24 января 2019

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

https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
В этом разделе документации обсуждается предостережение об обнаружении изменений 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}
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...