在 Vue 中过滤对象列表而不改变原始数据

use*_*231 2 vue.js vue-component vuejs2

我第一次深入 Vue 并尝试制作一个简单的过滤器组件,该组件从 API 获取数据对象并对其进行过滤。

下面的代码有效,但我无法找到一种方法来“重置”过滤器而不进行另一个 API 调用,这让我觉得我接近这个错误。

在 DOM 中显示/隐藏是否比更改数据对象更好?

HTML

<button v-on:click="filterCats('Print')">Print</button>

<div class="list-item" v-for="asset in filteredData">
    <a>{{ asset.title.rendered }}</a>
</div>
Run Code Online (Sandbox Code Playgroud)

Javascript

export default {
  data() {
    return {
      assets: {}
    }
  },
  methods: {
    filterCats: function (cat) {
      var items = this.assets
      var result = {}
      Object.keys(items).forEach(key => {
        const item = items[key]
        if (item.cat_names.some(cat_names => cat_names === cat)) {
          result[key] = item
        }
      })
      this.assets = result
    }
  },
  computed: {
    filteredData: function () {
      return this.assets
    }
  },
}
Run Code Online (Sandbox Code Playgroud)

acd*_*ior 7

在 DOM 中显示/隐藏是否比更改数据对象更好?

一点也不。改变数据是“Vue 方式”。

您无需修改assets即可过滤它。

推荐的方法是使用计算属性:您将创建一个filteredData依赖于cat数据属性的计算属性。每当您更改 的值时catfilteredData将自动重新计算(this.assets使用 的当前内容过滤cat)。

像下面这样:

new Vue({
  el: '#app',
  data() {
    return {
      cat: null,
      assets: {
      	one: {cat_names: ['Print'], title: {rendered: 'one'}},
        two: {cat_names: ['Two'], title: {rendered: 'two'}},
        three: {cat_names: ['Three'], title: {rendered: 'three'}}
      }
    }
  },
  computed: {
    filteredData: function () {
      if (this.cat == null) { return this.assets; } // no filtering
      var items = this.assets;
      var result = {}
      Object.keys(items).forEach(key => {
        const item = items[key]
        if (item.cat_names.some(cat_names => cat_names === this.cat)) {
          result[key] = item
        }
      })
      return result;
    }
  },
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <button v-on:click="cat = 'Print'">Print</button>

  <div class="list-item" v-for="asset in filteredData">
      <a>{{ asset.title.rendered }}</a>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)