【问题标题】:How to filter items based on multiple select dropdown with Vue JS?如何使用 Vue JS 基于多选下拉列表过滤项目?
【发布时间】:2021-01-08 08:05:50
【问题描述】:

我正在学习 vue.js,并且正在尝试使用多个下拉列表和按钮搜索进行案例研究搜索。我需要找到一个过滤功能,该功能将根据触发按钮搜索从几个下拉列表中的选择来过滤对象列表。

我有我在下面编写的代码,但是这个过滤器是实时工作的。选择其中一个下拉列表时,它将显示搜索结果。但是我想要的是,在选择几次下降后,搜索结果出现,并且必须单击“搜索”按钮,然后结果出现。

我一直在寻找一些参考资料并尝试过,但仍然没有得到我想要的结果。

new Vue({
  el: '#app',
  data: {
    selectedType: '',
    selectedCountry: '',
    selectedYear: '',
    items: [
      {
        name: 'Nolan',
        type: 'mercedes',
        year: '2020',
        country: 'england'
      },
      {
        name: 'Edgar',
        type: 'bmw',
        year: '2020',
        country:'belgium'
      },
      {
        name: 'John',
        type: 'bmw',
        year: '2019',
        country: 'england'
      },
      {
        name: 'Axel',
        type: 'mercedes',
        year: '2020',
        country: 'england'
      }
    ]
  },
  computed: {
    searchItem: function () {
      let filterType= this.selectedType,
          filterCountry = this.selectedCountry,
          filterYear = this.selectedYear
      
      return this.items.filter(function(item){
        let filtered = true
        if(filterType && filterType.length > 0){
          filtered = item.type == filterType
        }
        if(filtered){
          if(filterCountry && filterCountry.length > 0){
            filtered = item.country == filterCountry
          }
        }
        if(filtered){
          if(filterYear && filterYear.length > 0){
            filtered = item.year == filterYear
          }
        }
        return filtered
      })
    }
  }
})
.list-item{
  margin-top:50px;
}

.card{
  box-shadow:0px 10px 16px rgba(0,0,0,0.16);
  width:400px;
  padding:20px 30px;
  margin-bottom:30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.1/vue.js"></script>

<div id="app">
  <select v-model="selectedType">
    <option value="mercedes">Mercedes</option>
    <option value="bmw">BMW</option>
  </select>
  
  <select v-model="selectedCountry">
    <option value="belgium">Belgium</option>
    <option value="england">England</option>
  </select>
  
  <select v-model="selectedYear">
    <option value="2019">2019</option>
    <option value="2020">2020</option>
  </select>
  
  <button>Search</button>
  
  <div class="list-item" v-for="item in searchItem">
    <div class="card">
      <p>Name: {{ item.name }}</p>
      <p>Car: {{ item.type }}</p>
      <p>Year: {{ item.year }}</p>
      <p>Country: {{ item.country }}</p>
    </div>
  </div>
</div>

【问题讨论】:

  • computed 是被动的。这意味着每当计算中的反应性引用发生变化时,计算就会重新运行并且模板会更新。如果您不想要反应性,请改用方法并根据自己的逻辑运行它。

标签: javascript html vue.js vuejs2 dropdown


【解决方案1】:

考虑定义过滤方法,而不是使用computed

请看下面的例子

new Vue({
  el: '#app',
  data: {
    selectedType: '',
    selectedCountry: '',
    selectedYear: '',
    items: [{
        name: 'Nolan',
        type: 'mercedes',
        year: '2020',
        country: 'england'
      },
      {
        name: 'Edgar',
        type: 'bmw',
        year: '2020',
        country: 'belgium'
      },
      {
        name: 'John',
        type: 'bmw',
        year: '2019',
        country: 'england'
      },
      {
        name: 'Axel',
        type: 'mercedes',
        year: '2020',
        country: 'england'
      }
    ],
    searchResult: [],
  },
  methods: {
    search: function() {
      let filterType = this.selectedType,
        filterCountry = this.selectedCountry,
        filterYear = this.selectedYear

      this.searchResult = this.items.filter(function(item) {
        let filtered = true
        if (filterType && filterType.length > 0) {
          filtered = item.type == filterType
        }
        if (filtered) {
          if (filterCountry && filterCountry.length > 0) {
            filtered = item.country == filterCountry
          }
        }
        if (filtered) {
          if (filterYear && filterYear.length > 0) {
            filtered = item.year == filterYear
          }
        }
        return filtered
      })
    }
  },
  mounted() {
    this.search()
  }
})
.list-item {
  margin-top: 50px;
}

.card {
  box-shadow: 0px 10px 16px rgba(0, 0, 0, 0.16);
  width: 400px;
  padding: 20px 30px;
  margin-bottom: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.1/vue.js"></script>

<div id="app">
  <select v-model="selectedType">
    <option value="" disabled selected hidden>Type</option>
    <option value="mercedes">Mercedes</option>
    <option value="bmw">BMW</option>
  </select>

  <select v-model="selectedCountry">
    <option value="" disabled selected hidden>Country</option>
    <option value="belgium">Belgium</option>
    <option value="england">England</option>
  </select>

  <select v-model="selectedYear">
    <option value="" disabled selected hidden>Year</option>
    <option value="2019">2019</option>
    <option value="2020">2020</option>
  </select>

  <button @click="search">Search</button>

  <div class="list-item" v-for="item in searchResult">
    <div class="card">
      <p>Name: {{ item.name }}</p>
      <p>Car: {{ item.type }}</p>
      <p>Year: {{ item.year }}</p>
      <p>Country: {{ item.country }}</p>
    </div>
  </div>
</div>

【讨论】:

  • 很好!顺便说一句,我想问一下占位符。在正常的选择下拉列表中,当我们提供选项 &lt;option selected&gt; Year &lt;/option&gt; 时,它将是占位符。但是我在我的代码中这样尝试过,它没有出现。如何显示?
  • @frankfurt 关于占位符的问题,您可以添加optiondisabled selected hidden。请查看编辑
  • @frankfurt 如果您有类似type:"mercedes, audi" 的内容,并且希望在下拉菜单显示mercedes 时显示它,您将如何更改它以使其不只是寻找完全匹配的内容?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 1970-01-01
  • 2019-09-12
  • 2016-02-17
  • 2021-11-07
相关资源
最近更新 更多