Состояние Vuex не обновляется при мутации

1

В моем приложении 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 импортируется/используется, но это не решило проблему.

Теги:
vue.js
vuex

2 ответа

2
Лучший ответ

У меня нет всего вашего кода, но здесь, как я думаю, может случиться. Вы начинаете игру с начальным состоянием, которое вы импортировали. Во время игры вы обновляете состояние объекта, делая что-то вроде:

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

На самом деле происходит то, что ваше начальное состояние было обновлено, потому что у вас есть ссылка на объект, а не на его копию, поэтому при попытке сбросить состояние он остается неизменным, потому что вы случайно изменили исходный объект состояния.

Чтобы решить эту проблему, просто оберните исходное состояние в функцию (фабричную функцию), чтобы всегда возвращалось состояние init:

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/

  • 0
    Ваше решение работает! Но мне все еще любопытно, почему использование camera: {...initialCameraState} как для начального состояния, так и для мутации не работало. Я полагаю, что с помощью оператора распространения объекта значения копируются, а не на них ссылаются ...
  • 0
    @lysigk Теоретически оператор распространения должен клонировать объект, он отлично работает с Object.assign : jsfiddle.net/jrqmvvsz . Так что, честно говоря, я не уверен, что там происходит
0
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()
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню