admin管理员组

文章数量:1401176

In my Vue.js/Vuex based application I'm using this mutation to reset part of the Vuex state:

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

This way, things work out fine, but writing out the whole camera state seems pretty verbose to me. So I extracted the initial camera state into a seperate file:

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

I've refactored the resetGame() mutation like this:

import initialCameraState from './initialCameraState'

restartGame(state) {
    state.gameRunning = true

    state.camera = initialCameraState
}

But somehow this doesn't work, the Vuex store does not get updated but seems to just stay the same. How can this be?

I'm also using initialCameraState.js to set (part of) the initial state of the Vuex store. My first thought was that when mutating the according part of the state, initialCameraState is also being mutated. That would explain resetGame() not showing any effects. So I tried using the object spread operator in both places where initialCameraState.js gets imported/used, but this didn't solve the issue.

In my Vue.js/Vuex based application I'm using this mutation to reset part of the Vuex state:

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

This way, things work out fine, but writing out the whole camera state seems pretty verbose to me. So I extracted the initial camera state into a seperate file:

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

I've refactored the resetGame() mutation like this:

import initialCameraState from './initialCameraState'

restartGame(state) {
    state.gameRunning = true

    state.camera = initialCameraState
}

But somehow this doesn't work, the Vuex store does not get updated but seems to just stay the same. How can this be?

I'm also using initialCameraState.js to set (part of) the initial state of the Vuex store. My first thought was that when mutating the according part of the state, initialCameraState is also being mutated. That would explain resetGame() not showing any effects. So I tried using the object spread operator in both places where initialCameraState.js gets imported/used, but this didn't solve the issue.

Share Improve this question asked Nov 29, 2017 at 12:01 lsgnglsgng 4959 silver badges22 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

I don't have all your code, but here's what I think may be happening. You are initing the game with the initial state which you have imported. During the game you update the state of the object by doing something like:

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

What actually happens is that your initial state has been updated because you have a reference to the object, not a copy of it, so when you try to reset the state it just remains the same, because you have inadvertently changed the initial state object.

To solve this simply wrap the initial state in a function (a factory function) so that the init state always gets returned:

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

Here's a JSFiddle showing what happens without a function (the positions remain the same): https://jsfiddle/9qg8ws0x/

And here one with the function (the positions are reset): https://jsfiddle/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()
}

本文标签: javascriptVuex state not updating on mutationStack Overflow