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

时间:2016-10-14 18:35:39

标签: javascript arrays vue.js

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

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

...多个搜索字符串变得更加复杂。关于如何在StackOverflow上执行此操作已有几个问题,但答案很少。目前我正在尝试根据我的需要重新调整找到here的自定义过滤器,但它无效。

我的用例: 我有一组组(复选框),用户可以选择这些组来过滤一组人。每个人都被分配到一个或多个组,因此如果用户选择了任何其中一个组,那么该人应该出现。

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

    <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,则只显示Dave和Jill。如果用户随后检查Children,则应显示Dave,Jill和Sam。我太近了!

3 个答案:

答案 0 :(得分:1)

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

我会浏览每个演员,如果他们的任何一个团队都在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/

答案 1 :(得分:0)

由于过滤器已被弃用(在v-for中,请参阅比尔的评论),您应养成使用计算机来完成过滤的习惯。

(如果您使用的是IE,则无法在没有填充的情况下使用includes;您可以改用indexOf...>=0。)

&#13;
&#13;
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;
    }
  }
});
&#13;
<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>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

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>