Vuex和VueJS(不要在突变处理程序之外改变vuex存储状态)

Jay*_*n H 8 javascript firebase vue.js firebase-authentication vuex

我试图创建一个listenAuth会监视"功能onAuthStateChanged "在火力通知vuex店当用户登录或退出.据我所知,我只是使用变异处理程序修改state.authData,除非我遗漏了什么?

我收到错误:

[vuex] Do not mutate vuex store state outside mutation handlers.
Run Code Online (Sandbox Code Playgroud)

这是我的App.vue javascript(来自我的组件)

<script>
// import Navigation from './components/Navigation'
import * as actions from './vuex/actions'
import store from './vuex/store'
import firebase from 'firebase/app'

export default {
  store,
  ready: function () {
    this.listenAuth()
  },
  vuex: {
    actions,
    getters: {
      authData: state => state.authData,
      user: state => state.user
    }
  },
  components: {
    // Navigation
  },
  watch: {
    authData (val) {
      if (!val) {
        this.redirectLogin
        this.$route.router.go('/login')
      }
    }
  },
  methods: {
    listenAuth: function () {
      firebase.auth().onAuthStateChanged((authData) => {
        this.changeAuth(authData)
      })
    }
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

这是我的动作(changeAuth)功能

export const changeAuth = ({ dispatch, state }, authData) => {
  dispatch(types.AUTH_CHANGED, authData)
}
Run Code Online (Sandbox Code Playgroud)

这是我的商店(重要的部分)

const mutations = {
  AUTH_CHANGED (state, authData) {
    state.authData = authData
  }
}

const state = {
  authData: {}
}
Run Code Online (Sandbox Code Playgroud)

KF *_*Lin 10

我也遇到过这个问题.我的商店:

  state: {
    items: []
  },
  mutations: {
    SetItems (state, payload) {
      // Warning
      state.items = payload.items
    }
  },
  actions: {
    FetchItems ({commit, state}, payload) {
      api.getItemsData(payload.sheetID)
        .then(items => commit('SetItems', {items}))
    }
  }
Run Code Online (Sandbox Code Playgroud)

修复它替换state.items = payload.items为:

state.items = payload.items.slice()
Run Code Online (Sandbox Code Playgroud)

原因是数组在Javascript中存储为引用,并且payload.items很可能在Vuex之外进行更改.所以我们应该使用一个新的副本payload.items.

对于状态对象,请使用:

state.someObj = Object.assign({}, payload.someObj)
Run Code Online (Sandbox Code Playgroud)

并且不要使用JSON.parse(JSON.stringify(someObj))因为它慢得多.


gus*_*pch 5

在遇到相同问题后,我发现仅当我们尝试以Vuex状态存储身份验证/用户数据时,才会发生错误。

从...改变

const mutations = {
  AUTH_CHANGED (state, authData) {
    state.authData = authData
  }
}
Run Code Online (Sandbox Code Playgroud)

...至...

const mutations = {
  AUTH_CHANGED (state, authData) {
    state.authData = JSON.parse(JSON.stringify(authData))
  }
}
Run Code Online (Sandbox Code Playgroud)

会解决您的情况。

  • 出于某种原因,`Object.assign({}, authData)` 不起作用,但`JSON.parse(JSON.stringify(authData))` 可以。 (4认同)
  • `Object.assign` 有时不起作用的原因是它不执行深度复制,如文档中所述:“对于深度克隆,我们需要使用其他替代方案,因为 Object.assign() 复制属性值。如果源值是对对象的引用,则它仅复制该引用值。"` 。对于深度克隆,“JSON.parse(JSON.stringify(obj))”更好,即使它肯定会更慢 (2认同)