Vue JS 使用数组来过滤另一个数组

Vue JS use array to filterBy another array?

本文关键字:数组 另一个 过滤 JS Vue      更新时间:2023-09-26

是的,又是我。我正在尝试根据字符串数组过滤数组。因此,虽然使用 Vue 很容易使用单个字符串过滤器...

<div v-for="item in items | filterBy 'words' in 'property'">

。多个搜索字符串变得更加复杂。关于如何在StackOverflow上做到这一点已经有几个问题,但很少有答案。目前,我正在尝试根据我的需求重新调整此处找到的自定义过滤器的用途,但它不起作用。

我的用例:我有一个组数组(复选框(,用户可以选择这些组来筛选人员数组。每个人都被分配到一个或多个组,因此如果用户选择了他们的任何一个组,则该人员应该显示。

所以我的模板看起来像这样:

    <template v-for="group in ensemble_groups">
      <input name="select_group[]" id="group_@{{ $index }}"
        :value="group"
        v-model="selected_groups"
        type="checkbox">
      <label for="group_@{{ $index }}">@{{ group }}</label>
    </template>
    <template v-for="person in cast | filterBy selectGroups">
      <div>@{{ person.actor_name }}</div>
    </template>

您在那里看到我的自定义过滤器selectGroups吗?这是我的 Vue 数组:

  selected_groups: [],
  ensemble_groups: ["Leads","Understudies","Children","Ensemble"],
  cast: [
    {
      actor_name: "Dave",
      groups: ["Leads"],
    },
    {
      actor_name: "Jill",
      groups: ["Leads"],
    },
    {
      actor_name: "Sam",
      groups: ["Children","Ensemble"],
    },
    {
      actor_name: "Austin",
      groups: ["Understudies","Ensemble"],
    },
  ],

最后是自定义过滤器。我无法判断它是否被触发,因为当我单击组复选框时,没有任何反应。

filters: {
  selectGroups: function() {
    if (!selected_groups || selected_groups.length === 0) {
      return cast;
    }
    return this.recursiveFilter(cast, selected_groups, 0);
  }
},
methods: {
  recursiveFilter: function(cast, selected_groups, currentPosition) {
    if (currentPosition+1 > selected_groups.length)
      return cast;
    var new_cast;
    new_cast = cast.filter(function(person) {
      for (group of person.groups) {
        if (group.value == selected_groups[currentPosition])
          return true;
      }
    });
    return this.recursiveFilter(new_cast, selected_groups, currentPosition+1);
  }
}

因此,如果用户选择Leads则只显示戴夫和吉尔。如果用户随后选中Children,则应显示 Dave、Jill 和 Sam。我离得很近!

我会使用计算属性而不是过滤器和方法。

我会通过每个演员,如果他们的任何小组都在selected_groups我会允许它通过过滤器。我会这样使用Array.some.

results: function() {
  var self = this
  return self.cast.filter(function(person) {
    return person.groups.some(function(group) {
      return self.selected_groups.indexOf(group) !== 1
    })
  })
},

这是我设置的一个快速演示,可能会有用: http://jsfiddle.net/crswll/df4Lnuw6/8/

由于过滤器已被弃用(在v-for中,请参阅比尔的评论(,您应该养成制作计算来执行过滤操作的习惯。

(如果您使用的是 IE,则不能在没有 polyfill 的情况下使用 includes;您可以改用indexOf...>=0

new Vue({
  el: '#app',
  data: {
    selected_groups: [],
    ensemble_groups: ["Leads", "Understudies", "Children", "Ensemble"],
    cast: [{
      actor_name: "Dave",
      groups: ["Leads"],
    }, {
      actor_name: "Jill",
      groups: ["Leads"],
    }, {
      actor_name: "Sam",
      groups: ["Children", "Ensemble"],
    }, {
      actor_name: "Austin",
      groups: ["Understudies", "Ensemble"],
    }, ]
  },
  computed: {
    filteredCast: function() {
      const result = [];
      for (const c of this.cast) {
        if (this.anyMatch(c.groups, this.selected_groups)) {
          result.push(c);
        }
      }
      return result;
    }
  },
  methods: {
    anyMatch: function(g1, g2) {
      for (const g of g1) {
        if (g2.includes(g)) {
          return true;
        }
      }
      return false;
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script>
<div id="app">
  <template v-for="group in ensemble_groups">
    <input name="select_group[]" id="group_@{{ $index }}" :value="group" v-model="selected_groups" type="checkbox">
    <label for="group_@{{ $index }}">@{{ group }}</label>
  </template>
  <template v-for="person in filteredCast">
    <div>@{{ person.actor_name }}</div>
  </template>
</div>

var demo = new Vue({
    el: '#demo',
    data: {
        search: 're',
        people: [
          {name: 'Koos', age: 30, eyes:'red'},
          {name: 'Gert', age: 20, eyes:'blue'},
          {name: 'Pieter', age: 12, eyes:'green'},
          {name: 'Dawid', age: 67, eyes:'dark green'},
          {name: 'Johan', age: 15, eyes:'purple'},
          {name: 'Hans', age: 12, eyes:'pink'}
        ]
    },
    methods: {
      customFilter: function(person) {
          return person.name.indexOf(this.search) != -1
          || person.eyes.indexOf(this.search) != -1
          ;
      }
    },
   
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="demo">
    <input type="text" class="form-control" v-model="search"/>
    
    <br/>
    <table class="table">
      <thead>
        <tr>
          <th>name</th>
          <th>eyes</th>
          <th>age</th>
        </tr>
      </thead>
      <tr v-for="person in people | filterBy customFilter">
        <td>{{ person.name }}</td>
        <td>{{ person.eyes }}</td>
        <td>{{ person.age }}</td>
      </tr>
  </table>
</div>