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

时间:2019-01-23 01:16:29

标签: javascript vue.js vue-class-components

我不确定如何解决此问题,因为其中有很多问题,而且这种行为是我从未在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返回带有启动方法和其他游戏变量的对象。

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

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类中有一个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];
}

可以肯定的是,即使播放器和id很明显也返回了null。 当我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 个答案:

答案 0 :(得分:0)

与一位朋友一起解决问题之后,我发现根本的问题是涉及Vue的反应性的JavaScript特定问题。

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

  

Vue无法检测到属性的添加或删除。由于Vue在实例初始化期间执行getter / setter转换过程,因此数据对象中必须存在一个属性,以便Vue对其进行转换并使其具有反应性。

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

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

我要添加一个新属性,该属性在初始化时Vue尚未转换,并且Vue无法检测到此更改。这是我在开发游戏运行时时没有考虑到的简单概念。

为了正确设置新玩家,我决定使用传播运算符更改Vue正在反应的players对象的整体,然后Vue将检测到我的玩家正在像这样添加:

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

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