“sortItem”计算属性中的意外副作用

PCh*_*ana 1 javascript vue.js

当我使用 时sortItem,我收到以下错误:“在“sortItem”计算属性中出现意外的副作用”。我该如何解决这个问题?

computed:{
    sortItem(){
      return this.items.sort((a,b)=>{
        return b.time - a.time
      })
    }
  },
Run Code Online (Sandbox Code Playgroud)

Sum*_*ai8 7

您会收到此错误,因为Array.prototype.sort对数组进行了就地排序。

这意味着什么?

就地算法修改现有数据结构,而不是创建副本并修改该副本。这意味着您只有修改后的数据结构,而不是拥有一种原始数据结构和一种修改后的数据结构。这样做显然比制作副本更节省空间。

我们可以使用以下代码段轻松演示这一点。请注意,myUnsortedArray突然包含一个已排序的数组,即使我们在初始数组之后没有进行任何赋值。

let myUnsortedArray = [5, 4, 1, 3, 2];
console.log("Unsorted array", myUnsortedArray); // 5, 4, 1, 3, 2

let mySortedArray = myUnsortedArray.sort();
console.log("Sorted array", mySortedArray); // 1, 2, 3, 4, 5
console.log("Unsorted array again", myUnsortedArray); // 1, 2, 3, 4, 5
Run Code Online (Sandbox Code Playgroud)

为什么会报错

Vue 中的计算属性是纯函数

您可以定义计算属性的计算方式。在幕后,Vue 将确定您的计算属性依赖于哪些变量,并且每当依赖项之一发生变化并且计算属性在某处被使用时,都会默默地重新计算您的计算属性。

当您向计算属性引入副作用时,例如更改组件的本地状态,就会引入难以调试的行为。它对 Vue 何时以及如何重新计算计算属性进行了假设。相反,您应该将副作用放在方法中,或者如果您没有其他选择,则放在观察者中。

如何修复

“修复”它的一种方法是在排序之前复制数组。这样做的两种方法是:

[...this.items].sort((a, b) => b.time - a.time)
this.items.slice(0).sort((a, b) => b.time - a.time)
Run Code Online (Sandbox Code Playgroud)

更好的解决方法是,在您制作或添加项目列表时对项目列表进行排序。

进一步阅读

为了更好地理解这一点,我建议阅读“原语”、“引用”和“范围”。