【问题标题】:How do I sort a computed property by a value?如何按值对计算属性进行排序?
【发布时间】:2020-05-12 14:14:51
【问题描述】:

查看Vue.JS' documentation 后,我们提供了一个方法,例如,按所有偶数排序。这一切都很好,但我想按数组内的名称值对数组进行排序 - 这意味着我需要进行比较。我找到的所有答案都已被弃用,唯一的解决方案是使用 VueJS 本身以外的其他模块。这真的不可能,还是我只是错过了一些明显的东西? 这是我的例子:

data() {
    return {
        namesArray: []
        ]
    };
  },
...
computed: {
    addToNamesArray(){
        this.namesArray.push({"firstName": 'Charles', "lastName": 'Charleston'})
        this.namesArray.push({"firstName": 'Albert', "lastName": 'Alberterson'})
        this.namesArray.push({"firstName": 'Bertrand', "lastName: ''"})
        return this.namesArray
        //(Obviously more complicated in reality, but let's keep it simple)
    }
}

在 Vue 中:

<ul>
    <li v-for="(namesList, index) in addNamesToArray" :key="index">
        {{namesList.firstName}}
    </li>
</ul>

尝试在计算属性中进行排序会返回“计算属性中的意外副作用”错误,因为无法在计算属性内进行变异。所以我的第二次尝试是制作一个方法:

methods: {
    sortNames(){
        this.namesArray.sort((a,b) => a.firstName- b.firstName)
    }
}

产生新的计算属性:

computed: {
    addToNamesArray(){
        this.namesArray.push({"firstName": 'Charles', "lastName": 'Charleston'})
        this.namesArray.push({"firstName": 'Albert', "lastName": 'Alberterson'})
        this.namesArray.push({"firstName": 'Bertrand', "lastName: ''"})
        this.sortNames()
        return this.namesArray
    }
}

但这什么也没做(???)

如果有人能向我解释为什么这些解决方案不起作用并为我提供一个,我将不胜感激

【问题讨论】:

  • 正如错误消息所述。你不应该改变数据,即 this.namesArray.push 不应该存在。
  • 计算属性函数应该计算并返回一个 new 属性。他们不应该修改现有属性,特别是如果该属性是计算的依赖项。

标签: json vue.js


【解决方案1】:

好,我们从头说起:

我认为您应该首先将 addToNamesArray() 从 computed 移至 methods。所以你可以确定它只被调用一次,当你的数据发生变化时,computed 会被更频繁地调用。

你的函数 sortNames 应该被移动到计算域,像这样:

mounted(){
    this.addToNamesArray()
},
computed: {
     sortedNames(){
          return this.namesArray.concat().sort((a,b) => a.firstName.localeCompare(b.firstName))
     }
},
methods: {
     addToNamesArray(){
        this.namesArray.push({"firstName": 'Charles', "lastName": 'Charleston'})
        this.namesArray.push({"firstName": 'Albert', "lastName": 'Alberterson'})
        this.namesArray.push({"firstName": 'Bertrand', "lastName": ''})
     }
}

将它放置在计算属性中而不是方法中的原因是这会使值具有反应性,如果 namesArray 现在获得另一个元素,则整个列表将正确地重新渲染一次。方法不能正确地做到这一点。 我们创建 namesArray 的“副本”以不触及对象本身的数据,因为这也会触发重新渲染。

在 Vue 中你现在可以这样做:

<ul>
    <li v-for="(namesList, index) in sortedNames" :key="index">
        {{namesList.firstName}}
    </li>
</ul>

它没有排序的原因是因为'string'-'string' = NaN in javascript,所以我用localeCompare替换了它

【讨论】:

  • 'string'-'string' = NaN 刚刚抓住了我。它默默地失败了,所以很难被发现。添加比较功能可以修复它。 if (nameA nameB) { 返回 1; } // 名字必须相等 return 0;
【解决方案2】:

这里有几个问题:-

  1. 您不应该在computed 中修改this.namesArray,因为当它的某些反应性依赖项发生变化时,计算属性将重新评估。这可能会产生副作用,因为项目可能会多次插入 this.namesArray
  2. 所以,在 created 方法中更新 this.namesArray
  3. 然后使用localeCompare() 方法简单地通过firstNameaddNamesToArray 计算属性中对数组进行排序,例如:

new Vue({
  el: "#myApp",
  data() {
    return {
      namesArray: []
    }
  },
  created() {
    this.namesArray.push({"firstName": 'Charles',"lastName": 'Charleston'})
    this.namesArray.push({"firstName": 'Albert',"lastName": 'Alberterson'})
    this.namesArray.push({"firstName": 'Bertrand',"lastName": 'Doe'})
  },
  computed: {
    addNamesToArray() {
      return this.namesArray.sort((a, b) => a.firstName.localeCompare(b.firstName))
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <ul>
    <li v-for="(namesList, index) in addNamesToArray" :key="index">
      {{namesList.firstName}}
    </li>
  </ul>
</div>

【讨论】:

  • 这向我解释了这个问题,但它在我的上下文中不起作用 - 因为我正在处理的数据(实际上,不需要计算上面的示例代码)。但是非常感谢你的解释——这很有帮助!!!
【解决方案3】:

你可以试试这样,因为它是computed,它会在this.namesArray 更新时更新。

computed: {
    sortedNamesArray() {
        return this.namesArray.sort((a,b) => a.firstName - b.firstName);
    }
}

【讨论】:

  • 这仍然给出了“计算属性中的意外副作用”错误
  • @Nivyan 我的错,我以为你是在演示中添加到数组中的。正如其他答案所暗示的那样,您不应该更新计算中的数组。
  • 正是 :D 这就是我不得不绕开的。
猜你喜欢
  • 1970-01-01
  • 2022-01-13
  • 2019-10-02
  • 2020-03-02
  • 2018-10-15
  • 1970-01-01
  • 2013-02-12
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多