动态过滤Vue.js中的对象数组

时间:2017-11-17 15:44:05

标签: javascript vue.js

我有一个Vue.js应用程序。在这个应用程序中,我试图动态地将过滤器值应用于Array个对象。数组中的每个对象都有字段。我试图通过字段值过滤这些对象。每个字段都可以通过多个值进行过滤。

目前,我一直未能确定如何进行此过滤。我尝试过使用JavaScript的filter功能。但是,这总是为我返回一个空结果集。我已将此Fiddle放在一起,其中包含以下代码:

new Vue({
  el: '#app',
  data: {
    currentFilterProperty: '',
    currentFilterValue: '',

    cols: [
      { title: 'Name', prop:'name' },
      { title: 'Age', prop:'age' },
      { title: 'Birthday', prop:'birthday' },      
    ],

    dataFilters: [],
    data: [
      { name:'Patricia Miller', age:69, birthday:'04-15-1948' },
      { name:'Bill Baggett', age:62, birthday:'05-07-1955' },      
      { name:'Maxine Thies', age:21, birthday:'11-28-1995' },      
      { name:'Alison Battle', age:65, birthday:'08-07-1952' },      
      { name:'Dick Triplett', age:25, birthday:'08-27-1982' } 
    ]
  },

  methods: {
    addFilter: function() {
      var f = this.dataFilters[this.currentFilterProperty];
      if (!f) {
        this.dataFilters = {};
        this.dataFilters[this.currentFilterProperty] = [ this.currentFilterValue ];
      } else {
        this.dataFilters[this.currentFilterProperty].push(this.currentFilterValue);
      }

      // How to apply filter?
    }
  }
})

我不确定如何将过滤器应用于data对象。

3 个答案:

答案 0 :(得分:7)

完整的解决方案。最佳测试:添加过滤器年龄62,然后生日04-15-1948,然后添加名称Patricia中的'tri'。

new Vue({
  el: '#app',
  data: {
    filteredProperty: 'name',
    query: '',
    activeFilters: [],
    data: [
      {name: 'Patricia Miller', age: 62, birthday: '04-15-1948'},
      {name: 'Bill Baggett', age:62, birthday: '04-15-1948' },
      {name:'Maxine Thies', age:62, birthday:'11-28-1948'},
      {name:'Alison Battle', age:65, birthday:'08-07-1952'},      
      {name:'Dick Triplett', age:25, birthday:'08-27-1982'}
    ]
  },
  computed: {
    filtered () {
      var filtered = this.data
      this.activeFilters.forEach(filter => {
        filtered = filtered.filter(record => {
          return filter.name === 'name'
            ? new RegExp(filter.value, 'i').test(record[filter.name])
            : record[filter.name] == filter.value
        })
      })
      return filtered
    }
  },
  methods: {
    addFilter () {
      this.activeFilters.push({
        name: this.filteredProperty,
        value: this.query
      })
      this.query = ''
    },
    removeFilter (idx) {
      this.activeFilters.splice(idx, 1)
    }
  }
})
<div id="app">
  <div>
    <select v-model="filteredProperty">
      <option value="name">Name</option>
      <option value="age">Age</option>
      <option value="birthday">Birthdate</option>
    </select>
    <input placeholder="filter value" v-model="query">    
    <button @click="addFilter">add filter</button>
  </div>
  <hr>
  <table v-if="activeFilters.length">
    <tr style="width: 100px">
      <th colspan="3">Filters in use:</th>
    </tr>
    <tr v-for="(filter, index) in activeFilters" :key="index">
      <td>{{ _.capitalize(filter.name) }}:</td>
      <td>{{ filter.value }}</td>
      <td style="padding-left: 10px;">
        <a href="#" @click.prevented=removeFilter(index)>
          remove
        </a>
      </td>
    </tr>
  </table>
  <hr v-if="activeFilters.length">
  <table>
    <tbody>
      <tr v-for="(record, index) in filtered" :key="index">
        <td style="padding-right:18px;">{{ record.name }}</td>
        <td style="padding-right:18px;">{{ record.age }}</td>
        <td>{{ record.birthday }}</td>
      </tr>
    </tbody>
  </table>  
</div>

<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/lodash"></script>

答案 1 :(得分:0)

看看下面的代码。将您的方法更改为计算属性,然后过滤器可以自动发生而无需按下按钮。小提琴总是按名称进行过滤,因此您需要进行一些调整以适应所有过滤条件,但它应该让您朝着正确的方向前进。

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    currentFilterProperty: '',
    currentFilterValue: '',  
    cols: [
      { title: 'Name', prop:'name' },
      { title: 'Age', prop:'age' },
      { title: 'Birthday', prop:'birthday' }  
    ],
    data: [
      { name:'Patricia Miller', age:69, birthday:'04-15-1948' },
      { name:'Bill Baggett', age:62, birthday:'05-07-1955' },      
      { name:'Maxine Thies', age:21, birthday:'11-28-1995' },      
      { name:'Alison Battle', age:65, birthday:'08-07-1952' },      
      { name:'Dick Triplett', age:25, birthday:'08-27-1982' } 
    ]
  },
  computed:{
  	filteredData(){
    	var self = this;
        // Add condition for currentFilterProperty == 'Name'
    	if(this.currentFilterValue != undefined && this.currentFilterValue != ''){
      	return this.data.filter(function(d){
        	//alert(d.name + " " + this.currentFilterValue);
      		return d.name.indexOf(self.currentFilterValue) != -1;
      	});          
      }
      // else if(currentFilterProperty == 'Date'){
      // return this.data.filter(function(d){
        	
      		//return d.birthday.indexOf(self.currentFilterValue) != -1;
      //	});
      else{
      	return this.data;
      }    	
    }
  }
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.4/vue.min.js"></script>

<div id="app">
  <div>
    <select v-model="currentFilterProperty">
      <option v-for="c in cols" :value="c.prop">{{c.title}}</option>
    </select>
    
    <input placeholder="filter value" v-model="currentFilterValue" />
  </div>
  <hr />

  <table>
    <tbody>
      <tr v-for="(record, index) in filteredData">
        <td style="padding-right:18px;">{{ record.name }}</td>
        <td style="padding-right:18px;">{{ record.age }}</td>
        <td>{{ record.birthday }}</td>
      </tr>
    </tbody>
  </table>  
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

这是工作解决方案通过检查captaining条件

new Vue({
  el: '#app',
  data: {
    currentFilterProperty: 'name',
    currentFilterValue: '',
    filteredData:[],
    cols: [
      { title: 'Name', prop:'name' },
      { title: 'Age', prop:'age' },
      { title: 'Birthday', prop:'birthday' },      
    ],

    dataFilters: [],
    addFilters:[],
    data: [
      { name:'Patricia Miller', age:69, birthday:'04-15-1948' },
      { name:'Bill Baggett', age:62, birthday:'05-07-1955' },      
      { name:'Maxine Thies', age:21, birthday:'11-28-1995' },      
      { name:'Alison Battle', age:65, birthday:'08-07-1952' },      
      { name:'Dick Triplett', age:25, birthday:'08-27-1982' } 
    ]
  },
  
  methods: {
    addFilter: function() {
     if(!this.currentFilterValue){
      return false;
     }
      var obj = {};
      this.addFilters.push({name:this.currentFilterProperty,value:this.currentFilterValue});
      this.currentFilterValue = "";
    	var vm = this;
      this.dataFilters = this.data
      //var temp = [];
      for(var i in vm.addFilters){
        this.dataFilters = this.dataFilters.filter(function(a,b){
        return ((a[vm.addFilters[i].name]).toString().toLowerCase()).indexOf((vm.addFilters[i].value).toString().toLowerCase()) !== -1;
        });
      }
      // How to apply filter?
    }
  },
  mounted(){
    this.dataFilters = this.data;
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <div>
    <select v-model="currentFilterProperty">
      <option value="name">Name</option>
      <option value="age">Age</option>
      <option value="birthday">Birthdate</option>
    </select>
    <input placeholder="filter value" v-model="currentFilterValue" />
    
    <button v-on:click="addFilter">
    add filter
    </button>
  </div>
  <div v-for="(filter,index) in addFilters">{{filter.name}} : {{filter.value}}</div>
  <hr />

  <table>
    <tbody>
      <tr v-for="(record, index) in dataFilters">
        <td style="padding-right:18px;">{{ record.name }}</td>
        <td style="padding-right:18px;">{{ record.age }}</td>
        <td>{{ record.birthday }}</td>
      </tr>
    </tbody>
  </table>  
</div>