简体   繁体   English

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

[英]Vue JS use array to filterBy another array?

Yep, it's me again.没错,又是我。 I'm trying to filter an array based on an array of strings.我正在尝试根据字符串数组过滤数组。 So while a single string filter is easy with Vue...因此,虽然使用 Vue 可以轻松实现单个字符串过滤器...

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

...multiple search strings becomes more complex. ...多个搜索字符串变得更加复杂。 There's been several questions about how to do this on StackOverflow already, but very few answers.已经有几个关于如何在 StackOverflow 上执行此操作的问题,但答案很少。 Currently I'm trying to repurpose the custom filter found here for my needs, but it's not working.目前,我正在尝试根据我的需要重新调整此处找到的自定义过滤器的用途,但它不起作用。

My use case: I have an array of groups (checkboxes) that the user can select to filter an array of people.我的用例:我有一组组(复选框),用户可以选择这些组来过滤一组人。 Each person is assigned to one or more groups so if any one of their groups is selected by the user, that person should show up.每个人都被分配到一个或多个组,因此如果用户选择了其中的任何一个组,该人应该出现。

So my templates look like this:所以我的模板是这样的:

    <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>

You see my custom filter selectGroups there?你看到我的自定义过滤器selectGroups吗? Here's my Vue arrays:这是我的 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"],
    },
  ],

And finally here's the custom filter.最后是自定义过滤器。 I can't tell if it's even being triggered or not, because when I click on a group checkbox, nothing happens.我不知道它是否被触发,因为当我点击一个组复选框时,没有任何反应。

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);
  }
}

So if the user selects Leads only Dave and Jill should appear.因此,如果用户选择Leads只有 Dave 和 Jill 应出现。 If the user then checks Children , Dave, Jill, and Sam should appear.如果用户随后选中Children ,则应出现 Dave、Jill 和 Sam。 I'm so close!我离得那么近!

I would use a computed property instead of a filter and a method.我会使用计算属性而不是过滤器和方法。

I'd go through each cast member and if any of their groups is in selected_groups I'd allow it through the filter.我会检查每个演员,如果他们的任何组在selected_groups我会允许它通过过滤器。 I'd so this using Array.some .我会这样使用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
    })
  })
},

Here's a quick demo I set up, might be useful: http://jsfiddle.net/crswll/df4Lnuw6/8/这是我设置的快速演示,可能有用: http : //jsfiddle.net/crswll/df4Lnuw6/8/

Since filters are deprecated (in v-for , see Bill's comment), you should get into the habit of making computeds to do filtery things.由于过滤器已被弃用(在v-for ,请参阅 Bill 的评论),您应该养成使用计算来执行过滤操作的习惯。

(If you're on IE, you can't use includes without a polyfill; you can use indexOf...>=0 instead.) (如果您使用的是 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM