如何使用 .slice'd 数组修复 vuex 突变警告

Posted

技术标签:

【中文标题】如何使用 .slice\'d 数组修复 vuex 突变警告【英文标题】:How to fix a vuex mutation warning with a .slice'd array如何使用 .slice'd 数组修复 vuex 突变警告 【发布时间】:2021-12-18 01:51:12 【问题描述】:

我被这个错误弄疯了

[vuex] 不要在突变处理程序之外改变 vuex 存储状态

我有一个异步 vue/nuxt 方法,当用户想要编辑他/她的帖子时会触发该方法。我正在使用 vuex 的商店与我的 API 建立链接。 我在用户执行操作时使用组件数据来保存内容更改,这是一种基本配置。

当我尝试对媒体进行排序时出现错误。 无论我多么努力地尝试破坏引用,vue 都会不断向我大喊“不要改变外部处理程序”的错误。

代码如下:

async editSouvenir(id, data) 
  try 
    this.isLoading = true;
    if (this.filesToAdd) 
      for (let file of this.filesToAdd) 
        await this.$store.dispatch('media/CREATE_MEDIA', 
          souvenirId: id,
          file,
        );
        this.fileCtn++;
      
    

    if (data.mediaTab.length > 0) 
      let newOrder = 1;
      const newMediaTab = this.newMediaTab;
      // browsing media list
      const newArray = data.mediaTab.slice().sort((a, b) => 
        return newMediaTab.indexOf(a) - newMediaTab.indexOf(b);
      );

      // updating order
      for (let i = 0; i < newArray.length; i++) 
        newArray[i].order = i + 1;
      

      // saving media data
      data.mediaTab = newArray;
      console.log(data.mediaTab);
    

    this.isLoading = false;
    if (
      !this.createSouvenirError &&
      !this.createMediaError &&
      !this.postMediaError
    ) 
      await this.$store.dispatch('souvenir/EDIT',  id, data );
      this.$router.push(
        path: '/pns-editor',
        query:  selectedYear: data.date.substr(0, 4), souvenir: id ,
      );
     else 
      // @todo gérer l'erreur
    
   catch (err) 
    console.log(err);
    // this.isLoading = false;
  
,

vuex mutating 错误是由这一行触发的:

newArray[i].order = i + 1;

我要编辑的数组是帖子对象中的媒体对象数组。

 
    id: 1235354,
    title: 'my title',
    mediaTab: [
       ** my array of objects **
    ]

我不明白我在哪里改变存储状态数据。我已经阅读了几个关于 vuex 变异错误的答案,但我无法将它们与我的案例相匹配。

【问题讨论】:

这能回答你的问题吗? Vuex - Do not mutate vuex store state outside mutation handlers 另外,这篇文章可能是个好读物:flaviocopes.com/how-to-clone-javascript-object 【参考方案1】:

.slice 只为您的数组创建一个shallow copy,因此由于您正在更深入地访问它,因此它会抱怨突变,因为您仍然针对下面的参考 1 级。

一个解决方案是

<script>
import  cloneDeep  from 'lodash-es'

...
const newArray = cloneDeep(data.mediaTab)

它可能不像mentioned here 那样有奇怪的行为,因为它是lodash,你可以完全导入它并知道它已经过优化。 只是不要导入整个库,而只导入有用的方法,因此为什么要destructuring + lodash-es

PS:要小心,因为.sort also mutates 是一个数组。

【讨论】:

谢谢,我很生气唯一的解决方案是使用 lodash,但如果每个人都在使用它,我认为这是正确的做法 :) 我会小心的。 :) @fxguillois 这不是唯一的解决方案,而是 99% 防弹且高效的解决方案。此外,如果您通过 tree-shaking 仅导入所需的方法(如我的代码 sn-p 所示),这个库经过了超级实战测试和轻量级。 就像一个魅力。抱歉耽搁了,我在添加 lodash 后遇到了一个 docker 错误。 我说得太快了。 lodash-es 似乎与 nuxt 不兼容。我尝试了 transpile 选项,但杀死了页面中的羽毛笔和其他代码。现在尝试npmjs.com/package/lodash.clonedeep,但码头工人让我很痛苦。我会告诉你什么时候修好。我昨天在另一个站点(没有docker)中使用了你的答案,我没有缺点。奇怪。 @fxguillois lodash 正常兼容。只需安装lodash-es

以上是关于如何使用 .slice'd 数组修复 vuex 突变警告的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 localStorage 修复 Vuex 中的 JSON 解析错误

线上故障突突突?如何紧急诊断排查与恢复

在 Vue 3 中使用 Vuex 4 模块和 TypeScript,以及如何修复循环依赖 linting 错误?

如何使用 vuex 仅修改存储中的嵌套数组属性

组件未在商店更改时更新 - Vuex

如何在 VueJs 中将数组存储到 Vuex