0

我不知道如何解决这个问题,因为它有很多内容,而且这种行为是我以前从未在 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 类中有一个 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.logthis.user.id我得到4,并gameInterface.gameState.players为玩家返回一个带有 getter 的对象,如下所示:

{
  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 会因此而注意到一些变化并正确更新对象。有谁知道我在这里想念什么?

4

1 回答 1

0

在和朋友一起解决这个问题后,我发现根本问题是 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 没有检测到这种变化。这是我在开发游戏运行时时没有考虑到的一个简单概念。

为了正确设置新播放器,我决定使用扩展运算符来更改playersVue 正在响应的整个对象,反过来,Vue 会检测到我的播放器被添加,如下所示:

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

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

于 2019-01-24T01:01:28.200 回答