Vuex 状态不更新突变

Vuex state not updating on mutation

在我的基于 Vue.js/Vuex 的应用程序中,我使用这个突变来重置部分 Vuex 状态:

restartGame(state) {
    state.gameRunning = true

    state.camera = {
        position: {
            x: 0,
            y: 10,
            z: 0
        },
        moveForward: false,
        moveBackward: false,
        moveLeft: false,
        moveRight: false,
        velocity: {
            x: 0,
            z: 0
        },
        mouseMovement: {
            x: 0,
            y: 0
        },
        rotation: {
            x: 0,
            y: 0
        }
    }
}

通过这种方式,一切正常,但写出整个相机状态对我来说似乎很冗长。所以我将初始相机状态提取到一个单独的文件中:

initialCameraState.js

export default {
    position: {
        x: 0,
        y: 10,
        z: 0
    },
    moveForward: false,
    moveBackward: false,
    moveLeft: false,
    moveRight: false,
    velocity: {
        x: 0,
        z: 0
    },
    mouseMovement: {
        x: 0,
        y: 0
    },
    rotation: {
        x: 0,
        y: 0
    }
}

我重构了 resetGame() 突变,如下所示:

import initialCameraState from './initialCameraState'

restartGame(state) {
    state.gameRunning = true

    state.camera = initialCameraState
}

但不知何故这不起作用,Vuex 商店没有得到更新,但似乎只是保持不变。怎么会这样?

我还使用 initialCameraState.js 设置(部分)Vuex 存储的初始状态。我的第一个想法是,当改变状态的相应部分时,initialCameraState 也会被改变。这可以解释 resetGame() 没有显示任何效果。所以我尝试在 initialCameraState.js 得到 imported/used 的两个地方使用对象展开运算符,但这并没有解决问题。

我没有你的所有代码,但我认为可能会发生这种情况。您正在使用导入的初始状态启动游戏。在游戏过程中,您可以通过执行以下操作来更新对象的状态:

   state.camera['position'] = {
      x: 100,
      y: 100,
      z: 100
    }
  }

实际发生的是你的初始状态已经更新,因为你有一个对象的引用,而不是它的副本,所以当你尝试重置状态时,它只是保持不变,因为你无意中改变了初始状态对象。

要解决这个问题,只需将初始状态包装在一个函数(工厂函数)中,以便始终返回初始状态:

export default function() {
  return {    
    position: {
      x: 0,
      y: 10,
      z: 0
    },
    moveForward: false,
    moveBackward: false,
    moveLeft: false,
    moveRight: false,
    velocity: {
      x: 0,
      z: 0
    },
    mouseMovement: {
      x: 0,
      y: 0
    },
    rotation: {
      x: 0,
      y: 0
    }
  }
};

这是一个 JSFiddle,展示了没有函数会发生什么(位置保持不变):https://jsfiddle.net/9qg8ws0x/

这里有一个功能(位置已重置):https://jsfiddle.net/27xozazf/

export default {
  initializeCamera () {
    return {
      position: {
        x: 0,
        y: 10,
        z: 0
      },
      moveForward: false,
      moveBackward: false,
      moveLeft: false,
      moveRight: false,
      velocity: {
        x: 0,
        z: 0
      },
      mouseMovement: {
        x: 0,
        y: 0
      },
      rotation: {
        x: 0,
        y: 0
      }
    }
  }
}

import initial from './initial'

restartGame(state) {
  state.gameRunning = true
  state.camera = initial.initializeCamera()
}