【问题标题】:vuex: do not mutate vuex store state outside mutationvuex:不要在突变之外改变 vuex 存储状态
【发布时间】:2020-03-08 13:00:38
【问题描述】:

我有以下场景:

组件文本字段:

<v-text-field
  v-model="form.profile.mobile_business"
  label="Mobile"
  prepend-inner-icon="mdi-cellphone"
></v-text-field>

我通过以下方式获取当前值:

data() {
        return {
            form: {
                profile: JSON.parse(JSON.stringify(this.$store.getters["user/Profile"])),
            },
        };
    },

我有一个调用此方法的提交按钮:

updateUserProfile() {
            this.$store.dispatch("user/updateProfile", this.form.profile);
        }

一切都很完美。在我的商店调度中,我进行 API 调用并通过我的突变更新商店:

context.commit('UPDATE_PROFILE', profile);

在这一步之前没有错误。

但如果我再次更改表单输入 - 在我按下提交按钮后,我会得到:

vuex:不要在突变之外改变 vuex 存储状态

但我不想在我更改表单输入的值时更改 vuex 存储。 只有当有人点击提交按钮时才应该更新它。

【问题讨论】:

    标签: vue.js vuex vuetify.js store


    【解决方案1】:

    v-model 提供 2 路数据绑定。更改视图中的任何内容都会自动尝试直接更新模型,而不是通过突变。值得庆幸的是,Vue 允许在计算属性上使用 getset 来帮助我们解决这个问题。

    您应该在文本字段组件上执行的操作是使用 getset 方法添加一个计算属性。它看起来像这样:

    computed: {
      userProfile: {
        get() {
          JSON.parse(JSON.stringify(this.$store.getters["user/Profile"]));
        },
        set() {
          // only commit the changes to the form, do not submit the action that calls the API here. 
          this.$store.commit("user/updateProfile", this.form.profile) 
        }
    }
    

    您的 v-model 属性应该设置为这个新创建的属性,并且任何“设置”操作(读取:用户更改输入值)都将调用该操作,而不是尝试直接在 Store 中设置值.

    这是一个活生生的例子:CodePen

    【讨论】:

    • 感谢您的回答。如果我这样做,那么即使是文本字段的更改也会触发调度,对吗?我想要的是,用户必须通过我的提交按钮提交表单。我怎样才能做到这一点?
    • 你是对的。我很抱歉在你的帖子中遗漏了那一点。在这种情况下,每次输入更改时都会调用该操作,并且如果该操作负责使用表单数据进行调用...那么您将进行很多调用:) SO - 修复该问题,您只需要在计算属性的 set() 处理程序中提交突变。然后,在提交按钮上添加一个 @click 处理程序以提交 user/updateProfile 操作。如果您尚未创建突变来更新该州的配置文件,则需要这样做。我已经相应地更新了我的答案。
    • 再次感谢您的回答。但我什至不想将更改提交到商店。仅当用户点击提交按钮时,才应更新 API 和商店。我该如何存档?
    • 哦,在这种情况下,您只需要删除 v-model 指令,然后单击提交时才调用提交和调度!
    【解决方案2】:

    我是这样解决的:

    form: {
        profile: _.cloneDeep(this.$store.getters['user/Profile'])
      },
    

    并添加了一个监视处理程序:

    form: {
                handler: _.debounce(function (form) {
                    console.log("watch fired");
                }, 500), deep: true
            }
    

    因此,如果用户更改了值,则不会发生任何事情(除了我的 console.log 操作)。 如果他按下提交按钮,就会触发 store dispatch action。

    【讨论】:

      猜你喜欢
      • 2019-09-24
      • 2018-02-13
      • 2022-01-09
      • 1970-01-01
      • 2020-03-30
      • 2023-03-09
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多