【问题标题】:Mutation payload changes value by itself in vuex store mutation突变有效负载在 vuex 存储突变中自行更改值
【发布时间】:2020-03-22 10:44:36
【问题描述】:

我正在尝试使用 electron-vue 样板构建一个带有 VueJS 的 Electron 应用程序。我有一个突变,它根据接收到的有效负载更新部分状态。

然而,在动作调用和突变之间的某个地方,payload.myItem.id 属性会无意识地发生变化。 该动作由 Vue 模态组件调用:

    handleModalSave() {
      let payload = {
        layerId: this.layer.id,
        myItem: {
          id: this.editLayerForm.id,
          text: this.editLayerForm.text
        }
      }
      console.log('save', payload.myItem.id)
      this.$store.dispatch('addLayerItem', payload)
    }

这里说的是动作和突变:

  // Action
  addLayerItem: ({ commit }, payload) => {
    commit('ADD_LAYER_ITEM', payload)
  }

  // Mutation
  ADD_LAYER_ITEM: (state, payload) => {
    console.log('mutation', payload.myItem.id)
    let layer = state.map.layers.find(layer => layer.id === payload.layerId)

    if (payload.myItem.id !== '') {
      // Existing item
      let itemIdx = layer.items.findIndex(item => item.id === payload.myItem.id)
      Vue.set(layer.items, itemIdx, payload.myItem)
    } else {
      // New item
      payload.myItem.id = state.cnt
      layer.items.push(payload.myItem)
    }
  }

这是控制台日志的截图:

据我所知,没有命令可以在 console.log('save', payload)console.log('mutation', payload) 之间更改 myItem.id。我使用严格模式,所以没有其他函数可以改变突变之外的值。

编辑
我更新了 console.logs() 以直接显示属性而不是对象引用。

【问题讨论】:

  • 动作是什么样的?在调度调用和我们在这里缺少的突变之间有一个层。
  • @Dr_Derp 我加了action,没有特别的逻辑

标签: javascript vue.js electron vuex electron-vue


【解决方案1】:

据我所知,没有在console.log('save', payload)console.log('mutation', payload) 之间更改myItem.id 的命令。

它不需要在控制台日志记录之间更改

在您发布的图片中,您会在控制台日志记录旁边看到一个小的蓝色 i 图标。如果您将鼠标悬停在上面,您会得到一个解释,显示的值刚刚被评估。

当您将对象记录到控制台时,它会获取对该对象的引用。它不需要副本。复制不实用的原因有很多,因此甚至不尝试。

当您通过在控制台中单击来展开该对象时,它会在您单击时获取其属性的内容。这可能与记录对象时的值大不相同。

如果您想知道记录时的值,则可以使用JSON.stringify 将对象转换为字符串。但是,这假设它可以安全地转换为 JSON,这并不普遍。

另一种方法是将日志记录更改为直接针对您关心的属性。 console.log(payload.myItem.id)。这将通过仅记录不可变的字符串/数字来避免实时记录的问题。

更改id 的行似乎是:

payload.myItem.id = state.cnt

正如已经讨论过的,这在日志记录之后发生是无关紧要的。控制台尚未获取该属性的价值。它只引用了payload 对象。

对我来说唯一的谜团是您登录到控制台的两个对象都没有更新以反映新的 ID。在代码中它们似乎是同一个对象,所以我希望它们在您展开它们时是相同的。此外,其中一个对象显示了反应性 getter 和 setter 的证据,而另一个则没有。我可以推测为什么会这样,但很可能是由尚未提供的代码引起的。

我使用严格模式,所以没有其他函数可以改变突变之外的值。

严格模式仅适用于更改商店state 中的属性。此处考虑的对象在发生突变之前不会保存在存储区state 中。因此,如果要在突变运行之前更改 id,它不会触发有关严格模式的警告。

【讨论】:

  • 感谢您的回答,非常感谢!我更新了日志以显示属性payload.myItem.id,它仍然在日志中显示该值,然后再将其分配到突变中。这真的很令人沮丧,因为我无法识别没有分配 ID 的新项目。为了进一步检查问题,您是否需要特别查看任何代码?我也包括了这个动作,因为这应该是在 $emit 和突变之间被调用的唯一代码部分,对吧?
  • @user2307798 尝试在操作开始时添加一些日志记录,以检查 id 在该点是否正确。我注意到您没有使用命名空间。您是否有可能有 addLayerItem 操作或 ADD_LAYER_ITEM 突变是不同的模块?如果你这样做了,他们也会被调用。最后要尝试的是在调用dispatch 之前添加debugger 语句。你可能不得不进入一些你并不真正理解的代码,但应该很明显一行是否会改变id
  • 我在操作中添加了console.log('action', payload.myItem.id),在 DevTools 控制台中看不到实际日志。但是,我可以在终端中看到日志。如果您不了解 Electron,您可以在终端中启动您的应用程序,并且还会有日志进入终端。我使用了第一句话中链接的 vue-electron 样板。要回答您的其他问题,这是我所有商店模块中唯一一个名为 addLayerItem 的操作/突变。您有关于如何包含调试器语句的任何详细信息吗?
  • @user2307798 您提到您可以在终端中看到日志记录,但您没有提及您看到的值。关于调试器语句,您只需将单词debugger 单独写在一行上,它会导致执行在该行停止,就像断点一样。然后,您可以逐行浏览。我不熟悉 Electron,所以我不知道它是否有内置调试器。如果没有,您可能需要连接远程调试器。
  • 它在终端中显示正确的值(空字符串)。奇怪的是,在终端中,“突变”日志也显示了正确的值(空字符串)。显示错误值的是 DevTools 控制台和 Vue DevTools。我还使用了调试器,在某些时候,它卡在了 client.js 中名为 handleMessage(event) 的函数中。
【解决方案2】:

好的,我找到了问题的根本原因。 Vuex 被配置为使用createPersistedState 插件,该插件将数据存储在本地存储中。不知何故,存在一个问题,数据在实际存储和本地存储之间混淆了。在 main.js 中添加一个简单的window.localStorage.clear() 即可解决问题!

【讨论】:

    猜你喜欢
    • 2020-03-08
    • 2020-11-15
    • 2021-09-08
    • 2021-11-30
    • 2021-07-05
    • 2021-02-03
    • 2019-09-24
    • 2019-11-30
    • 2018-02-13
    相关资源
    最近更新 更多