【问题标题】:Vue mapState object is mutating vuex stateVue mapState 对象正在改变 vuex 状态
【发布时间】:2020-08-13 17:27:07
【问题描述】:

我有一个很奇怪的问题,因为在开发电子应用程序时,这个问题没有出现在 Quasar 中。但是这个有 vue-cli 的就让人沮丧了。

所以我有 vuex 状态,我有我的测试数据

export default function() {
  return {
    profile: {
      avatar: null,
      name: 'Thomas Smith',
      contact: 'thomas.smith@bootiq.io',
      branch: 'BIQ-PRAGUE',
      position: 'Software Developer / UI Designer',
      projects: [
        {
          company: 'Company',
          project: 'E-Shop Platform',
          role: 'Frontend Developer, Consultant'
        },
        {
          company: 'BIQ-INTERNAL',
          project: 'Skillboard',
          role: 'UI Design, Project Lead'
        }
      ],
      interests: ['Frontend Applications', 'UI Design', 'Stalking random people'],
      skills: [
        {
          name: 'Javascript',
          level: 2
        },
        {
          name: 'Vue',
          level: 3
        },
        {
          name: 'Angular',
          level: 1
        }
      ]
    }
  }
}

现在我有了用于编辑个人资料数据的组件

computed: {
    ...mapState({
      stateSkillList: state => state.skill.skillList
    }),

    ...mapGetters({
      user: 'user/getUser'
    })
  },

  mounted() {
    if (this.user) {
      this.data = Object.assign({}, this.data, this.user)

      if (this.data.projects.length === 0) {
        this.data.projects = [this.baseItems.projects]
      }

      if (this.data.skills.length) {
        this.filterSkillList()
      }
    }
  },

现在我的问题。我有输入,其中 v-model 是 data.name、data.contact 等,一切正常。但是当我尝试从 data.skill 数组或 data.projects、data.interests 添加/删除技能时,我得到了

vue.esm.js?a026:628 [Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers."

(found in <Root>)
warn @ vue.esm.js?a026:628
logError @ vue.esm.js?a026:1893
globalHandleError @ vue.esm.js?a026:1888
handleError @ vue.esm.js?a026:1848
run @ vue.esm.js?a026:4579
update @ vue.esm.js?a026:4551
notify @ vue.esm.js?a026:739
mutator @ vue.esm.js?a026:891
handleRemoveSkill @ EditProfile.vue?05c4:306
click @ EditProfile.vue?0ae8:411
invokeWithErrorHandling @ vue.esm.js?a026:1863
invoker @ vue.esm.js?a026:2188
original._wrapper @ vue.esm.js?a026:7565
vue.esm.js?a026:1897 Error: [vuex] do not mutate vuex store state outside mutation handlers.
    at assert (vuex.esm.js?2f62:90)
    at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:814)
    at Watcher.run (vue.esm.js?a026:4577)
    at Watcher.update (vue.esm.js?a026:4551)
    at Dep.notify (vue.esm.js?a026:739)
    at Array.mutator (vue.esm.js?a026:891)
    at VueComponent.handleRemoveSkill (EditProfile.vue?05c4:306)
    at click (eval at ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"6bb1df4e-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vuetify-loader/lib/loader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/EditProfile.vue?vue&type=template&id=7b259475&scoped=true& (app.js:1178), <anonymous>:414:44)
    at invokeWithErrorHandling (vue.esm.js?a026:1863)
    at HTMLButtonElement.invoker (vue.esm.js?a026:2188)

我不知道为什么。这是简单的功能

handleAddSkill(name) {
  this.data.skills.push({ name })
  this.dataSkillFilteredList = this.dataSkillFilteredList.filter(item => item !== name)
  this.dataSkillList = this.dataSkillFilteredList
},

感谢您的意见

【问题讨论】:

  • 没有minimal reproducible example 就无法回答您的问题,而且您迄今为止发布的内容不足以创建一个。如果您需要多文件节点环境,请使用 codesandbox.io 或类似的。

标签: vue.js state vuex


【解决方案1】:

您已复制状态并尝试更改该副本。这就是 vuex 警告你的原因。通过这样做,依赖于特定 vuex 状态的组件将不会获得您更新的新数据,因为您在 vuex 存储之外变异并编辑其副本。如果你真的想改变状态,你应该在 vuex 存储中使用它的 mutation 函数 来真正更新原始状态。 Vuex 甚至允许您直接更新 vuex 状态而无需变异函数(例如将 vuex 计算属性设置为 v-model)。因为它还更新了原始状态(但是错误)。但是你做的方式根本不会影响原来的 vuex 商店,而且 vuex 似乎也不喜欢那样。因此,解决方案是使用 mutation 函数,但如果您的数据太多无法处理,您可以直接使用 getterssetters 更改计算属性(见鬼,你甚至不必使用 getterssetters)。第一种方式是首选

【讨论】:

  • 但是当我输入输入时,其中 v-model="data.name" 没有发生任何不好的事情,并且 vuex 是相同的,但是组件中的对象 this.data 也在发生应有的变化我使用 Object.assign 来创建单独的对象,所以我不知道它为什么不起作用,是的,我想更改 vuex 状态,但是在提交我的更改后
  • 那么我怎样才能制作该状态的副本并安全地更改它?
  • 就像我说的,这只是一个警告。你可以忽略它。但是,如果您不想忽略它,这就是我为解决该问题所做的。我直接更改了 vuex store 的计算属性。在用户单击保存按钮之前,我会保留后端请求以进行保存。如果用户没有点击保存按钮,而是点击了取消按钮,我会再次从 api 请求我的原始数据:按原样制作。
猜你喜欢
  • 2018-11-04
  • 2019-09-25
  • 2020-10-22
  • 2021-04-10
  • 2021-12-10
  • 1970-01-01
  • 2020-08-04
  • 2018-08-17
  • 1970-01-01
相关资源
最近更新 更多