Vue.js:如何使用自定义过滤器过滤表

时间:2018-01-11 07:12:09

标签: javascript vue.js

表格有两列NameAge。搜索按名称工作。当您键入用户名时,表将减少为特定用户名。

但我希望使用比较运算符<>按年龄过滤它。

Code pen link

HTML

<div id="demo" class="container">
  <div class="row">
    <div class="col-md-6">
      <input v-model="search" class="form-control" placeholder="Username to search">
    </div>
    <div class="col-md-1">
      <select class="form-control" v-model="searchOperator">
        <option value=">">></option>
        <option value="<"><</option>
      </select>
    </div>
    <div class="col-md-5">
      <input v-model="searchName" class="form-control" placeholder="Age">
    </div>
  </div>
  <table class="table table-striped">
    <thead>
      <tr>
        <th v-repeat="column: columns">
          <a href="#" v-on="click: sortBy(column)" v-class="active: sortKey == column">
            {{ column | capitalize }}
          </a>
        </th>
      </tr>
    </thead>

    <tbody>
      <tr v-repeat="users | filterBy search | orderBy sortKey reverse">
        <td>{{ name }}</td>
        <td>{{ age }}</td>
      </tr>
    </tbody>
  </table>
</div>

Vue:

new Vue({
  el: '#demo',

  data: {
    sortKey: 'name',

    reverse: false,

    searchName: '',

    searchOperator: '',

    searchAge: '',

    columns: ['name', 'age'],

    newUser: {},

    users: [
      { name: 'John', age: 50 },
      { name: 'Jane', age: 22 },
      { name: 'Paul', age: 34 }
    ]
  },

  methods: {
    sortBy: function(sortKey) {
      this.reverse = (this.sortKey == sortKey) ? ! this.reverse : false;

      this.sortKey = sortKey;
    }
  }
});

实现这一目标的最佳方法是什么?我尝试过,但似乎没有任何工作。

1 个答案:

答案 0 :(得分:0)

首先是:v-repeat已被弃用。所以你应该使用v-for代替。

<tr v-for="user in filteredPersons">
  <td>{{ user.name }}</td>
  <td>{{ user.age }}</td>
</tr>

filteredPersons是返回数组的计算函数的名称:

computed: {
    filteredPersons: function () {
      return this.users
      .filter(this.filterByName)
      .filter(this.filterByAge)
      .sort(this.orderBy);
    }
  }

它通过组合两个过滤器函数和一个比较器函数来过滤和排序users数组:

methods: {
    filterByName : function(user) {
      // no search, don't filter : 
      if (this.searchName.length === 0) {
        return true;
      }

      return  (user.name.toLowerCase().indexOf(this.searchName.toLowerCase()) > -1);
    }, 
    filterByAge : function (user) {
      // no operator selected or no age typed, don't filter : 
      if (this.searchOperator.length === 0 || this.age.length === 0) {
        return true;
      }

      if (this.searchOperator === '>') {
        return (user.age > this.age); 
      } else  if (this.searchOperator === '<') {
        return (user.age < this.age);
      }      
    }, 
    orderBy : function (userA, userB) {
      let condition = (userA[this.sortKey] > userB[this.sortKey]);
      if (this.reverse) {
        return !condition;
      } else {
        return condition;
      }
    }
  },

工作片段:

new Vue({
  el: '#demo',

  data: {
    sortKey: 'name',
    reverse: false,
    searchName: '',
    searchOperator: '',
    searchAge: '',
    columns: ['name', 'age'],
    newUser: {},
    search: "",
    name: "",
    age: "",

    users: [
      { name: 'John', age: 50 },
      { name: 'Jane', age: 22 },
      { name: 'Paul', age: 34 },
      { name: 'Kate', age: 15 },
      { name: 'Amanda', age: 65 },
      { name: 'Steve', age: 38 },
      { name: 'Keith', age: 21 },
      { name: 'Don', age: 50 },
      { name: 'Susan', age: 21 }
    ]
  },
  methods: {
    sortBy: function (sortKey) {
      this.reverse = (this.sortKey == sortKey) ? !this.reverse : false;

      this.sortKey = sortKey;
    }, 
    filterByName : function(user) {
      // no search, don't filter : 
      if (this.searchName.length === 0) {
        return true;
      }

      return  (user.name.toLowerCase().indexOf(this.searchName.toLowerCase()) > -1);
    }, 
    filterByAge : function (user) {
      // no operator selected or no age typed, don't filter : 
      if (this.searchOperator.length === 0 || this.age.length === 0) {
        return true;
      }

      if (this.searchOperator === '>') {
        return (user.age > this.age); 
      } else  if (this.searchOperator === '<') {
        return (user.age < this.age);
      }      
    }, 
    orderBy : function (userA, userB) {
      let condition = (userA[this.sortKey] > userB[this.sortKey]);
      if (this.reverse) {
        return !condition;
      } else {
        return condition;
      }
    }
  },
  computed: {
    filteredPersons: function () {
      return this.users
      .filter(this.filterByName)
      .filter(this.filterByAge)
      .sort(this.orderBy);
    }
  },  
});
body {
  margin: 2em 0;
}

a {
  font-weight: normal;
  color: blue;
}

a.active {
  font-weight: bold;
  color: black;
}
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"/> 
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="index.js" defer></script>

</head>
<body>
<div id="demo" class="container">
  <div class="row">
    <div class="col-md-6">
      <input v-model="searchName" class="form-control" placeholder="Username to search">
    </div>
    <div class="col-md-1">
      <select class="form-control" v-model="searchOperator">
        <option value=">">></option>
        <option value="<"><</option>
      </select>
    </div>
    <div class="col-md-5">
      <input v-model="age" class="form-control" placeholder="Age" type="number">
    </div>
  </div>
  <table class="table table-striped">
    <thead>
      <tr>
        <th v-for="column in columns">
         <!-- <a href="#" v-on="click: sortBy(column)" >-->
         <!--  <a href="#"> -->
          <a href="#" v-on:click="sortBy(column)" v-bind:class="{active: sortKey == column}">
           
            <!--{{ column | capitalize }}-->
            {{column}}
          </a>
        </th>
      </tr>
    </thead>

    <tbody>
      <tr v-for="user in filteredPersons">
        <td>{{ user.name }}</td>
        <td>{{ user.age }}</td>
      </tr>
    </tbody>
  </table>
</div>
</body>
</html>