在调用 JSON.stringify() 之前 Vue 数据不可用

Vue data not available until JSON.stringify() is called

我不确定如何解决这个问题,因为其中涉及很多内容,而且这种行为是我以前从未在 JavaScript 或 Vue.js 中见过的 当然,我会尽量将代码保持在最关键的部分

我正在使用 vue-class-component(6.3.2),所以我的 Vue(2.5.17) 组件看起来像 classes :) 这个特定的组件看起来像这样:

import GameInterface from '@/GameInterface';

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

GameInterface return 具有启动方法和其他游戏变量的对象。

在游戏界面文件中,方法看起来像这样:

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

太棒了,它起作用了,该对象被传递到我的 Phaser 游戏 :) 并且它也被该方法 return 编辑了,这意味着 Vue 现在可以使用这个对象了。

在某些时候,我的 Vue class 中有一个 getter 方法,看起来像这样:

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];
}

果然,null 被 return 编辑了,尽管播放器和 ID 显然在那里。 当我 console.log this.user.id 我得到 4,并且 gameInterface.gameState.players returns 一个带有 getters 的对象,这样的玩家:

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

好的,所以它不会 return 播放器,即使对象和键被正确传递...

但是我发现了一个非常奇怪的方法来解决"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];
}

它成功地return为我们设置了当前玩家...奇怪不?

我的猜测是,当我们这样做时,我们 "bump" 对象,Vue 注意到一些变化因此正确更新对象。有人知道我在这里错过了什么吗?

在与一位朋友一起解决这个问题后,我发现潜在的问题是一个 JavaScript 特定的问题,涉及 Vue 的反应性质。

https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
在文档的这一部分中,讨论了 Vue 的变更检测的警告:

Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.

在我的游戏 运行 时,我这样设置玩家:

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

我正在添加一个新的 属性,Vue 在初始化时还没有转换,Vue 没有检测到这个变化。这是我在开发游戏时没有考虑到的一个简单概念 运行-time.

为了正确设置新玩家,我决定使用展开运算符来更改整个 players 对象,Vue 会对此做出反应,反过来,Vue 会检测到我的像这样添加玩家:

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

Vue 还讨论了另一种称为 $set 的方法,您可以在同一页上阅读。