搜索和过滤功能仍然无法正常工作(Vue JS)

Posted

技术标签:

【中文标题】搜索和过滤功能仍然无法正常工作(Vue JS)【英文标题】:Search and filter features still doesn't work properly (Vue JS) 【发布时间】:2021-04-21 19:17:36 【问题描述】:

我正在弄清楚我的搜索和过滤功能如何才能正常工作。 我创建了一个搜索功能,并通过stockdistancepricetime response 从搜索结果中过滤。我的搜索功能运行良好。但是我做的过滤功能还是不行。

我想在我进行搜索后,并想进一步过滤搜索,当下拉列表之一发生变化时,有股票和距离等选项,搜索结果项也会根据过滤器(例如:股票)发生变化可用与否。 还有其他过滤器,例如价格和时间响应。当我点击价格时,商品将按照最低价格到最高价格进行排序。而当我点击时间响应时,搜索项会按照响应快到晚的顺序排列。

示例案例

Type 中,我选择BMW。然后我点击搜索按钮。将显示类型为 BMW 的 2 项结果。然后,在过滤器Distance 中,我选择500 KM。它应该只显示 1 个结果。但是过滤器不起作用。

如果有 6 个商品结果,并且我点击price,商品将从最低价到最高价排序

我做了如下代码,谁能帮我解决这个问题?

new Vue(
  el: '#app',
  data: 
    selectedType: '',
    selectedCountry: '',
    selectedYear: '',
    selectedStock:'',
    selectedDistance:'',
    items: [
        name: 'Carthy',
        type: 'mercedes',
        year: '2020',
        country: 'england',
        stock: 'available',
        distance: '500',
        price: '1900',
        response: 'fast'
      ,
            
        name: 'Holand',
        type: 'mercedes',
        year: '2020',
        country: 'england',
        stock: 'available',
        distance: '500',
        price: '1050',
        response: 'fast'
      ,
      
        name: 'Nolan',
        type: 'mercedes',
        year: '2020',
        country: 'england',
        stock: 'available',
        distance: '500',
        price: '1000',
        response: 'fast'
      ,
      
        name: 'Edgar',
        type: 'bmw',
        year: '2020',
        country: 'belgium',
        stock: 'available',
        distance: '5000',
        price: '1200',
        response: 'fast'
      ,
      
        name: 'John',
        type: 'bmw',
        year: '2019',
        country: 'england',
        stock: 'available',
        distance: '500',
        price: '1500',
        response: 'fast'
      ,
      
        name: 'Axel',
        type: 'mercedes',
        year: '2020',
        country: 'england',
        stock: 'sold',
        distance: '500',
        price: '1600',
        response: 'late'
      
    ],
    searchResult: [],
    itemsToShow: 2,
    totalItems: 0,
    sortByPrice: true,
    sort: 'price',
    sortByTime: true,
    sort: 'time'
  ,
  computed:
    filterItem: function() 
      let filterStock = this.selectedStock,
        filterDistance = this.selectedDistance

      return this.searchResult.filter(function(item) 
        let filtered = true
        if (filterStock && filterStock.length > 0) 
          filtered = item.stock == filterStock
        
        if (filtered) 
          if (filterDistance && filterDistance.length > 0) 
            filtered = item.distance == filterDistance
          
        
        return filtered
      )
    
  ,
  methods: 
    search: function() 
      let filterType = this.selectedType,
        filterCountry = this.selectedCountry,
        filterYear = this.selectedYear

      this.itemsToShow = 2;
      
      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
      )
    ,
    priceSort: function()
        this.sortByPrice = !this.sortByPrice
      if(this.sortByPrice)
      this.sort = 'price'
    ,
    timeSort: function()
        this.sortByTime = !this.sortByTime
      if(this.sortByTime)
      this.sort = 'time'
    
  ,
  mounted() 
    this.search()
  
)
.list-item
  margin-top:50px;


#app
  position:relative;
  padding-bottom: 200px;


span
  margin: 0 15px;
  cursor:pointer;


.filter-box
  margin-top:15px;


.card
  box-shadow:0px 10px 16px rgba(0,0,0,0.16);
  width:400px;
  padding:20px 30px;
  margin-bottom:30px;


button
  background-color: #1cf478;
  border:none;
  padding: 10px 25px;
  font-weight:bold;
  border-radius: 15px;


select
  border:none;
  padding: 10px 15px;
  background-color:#c1c1c1; 
  border-radius:10px;
<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">
  <div class="search-box">
    <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>
  
  <div class="filter-box">
    <h6>Filter:</h6>
    <select v-model="selectedStock" @change="filterItem">
      <option value="" disabled selected hidden>Stock</option>
      <option value="sold">Sold</option>
      <option value="available">Available</option>
    </select>
    
    <select v-model="selectedDistance" @change="filterItem">
      <option value="" disabled selected hidden>Kilometers</option>
      <option value="500">500 KM</option>
      <option value="5000">5000 KM</option>
      <option value="10000">10.000 KM</option>
    </select>
    
    <span class="price" @click="priceSort">Price</span>
    <span class="response" @click="timeSort">Time Response</span>
    
  </div>

  <section class="result">
    <div class="container-fluid">
        <div class="row list-item" v-for="(item, id) in searchResult" :key="id">
          <div class="col-3 card" v-if="id < itemsToShow">
            <p>Name:  item.name </p>
            <p>Car:  item.type </p>
            <p>Year:  item.year </p>
            <p>Country:  item.country </p>
            <p>Price: $ item.price </p>
            <p>stock:  item.stock </p>
            <p>distance:  item.distance </p>
          </div>
        </div>
      
        <div class="row">
          <div class="col-12">
            <button @click="itemsToShow += 1">Load More</button>
          </div>
        </div>
    </div>
  </section>
</div>

【问题讨论】:

你在哪里调用filterItem计算属性? 我想在stockdistance过滤器@YashMaheshwari中使用它 【参考方案1】:

请参阅此codesandbox 以获取基于您的代码的工作演示。

我的改变

    datasearchResult 之上添加filterResult 以处理过滤结果,我们只将filterResult 渲染为结果。这会将“搜索”和“过滤”的逻辑分开,逻辑更清晰。 每当过滤器选择的值发生变化时,我们都会触发filterItems 方法作为@click 处理程序。 (之前您使用的是计算属性,这不够简单,我们可以简单地调用 @change 的方法并更新 filter results 数据。 每当触发搜索时,我们都会重置过滤器选择值,并显示所有搜索结果(filterResult 将与 searchResult 相同,因为没有过滤器值)。 关于排序,对于span这两个排序元素,我们只能更新this.sort数据,只要排序条件发生变化,就使用watch触发sortItems方法,这样会更简单。您可能需要根据您的需要调整sortItems 方法。当然,您可以为这两个“排序”按钮编写两个单独的方法,这完全取决于您:)

【讨论】:

【参考方案2】:

使用@change 事件并调用filterItem 计算属性。只要更改选择值,将调用计算的属性。

<select v-model="selectedStock" @change="filterItem">

【讨论】:

还是没有解决问题。尝试使用Mercedes 选项类型进行搜索,然后过滤距离并选择500。带有 BMW 品牌的商品也将被过滤@YashMaheshwari

以上是关于搜索和过滤功能仍然无法正常工作(Vue JS)的主要内容,如果未能解决你的问题,请参考以下文章

使用 vue.js 注册自定义过滤器

Vue js:Vuetify 服务器端数据表搜索过滤器不起作用

过滤数组时JS过滤器无法正常工作

ReactJS无法使搜索过滤器(文本)正常工作

剑道下拉过滤器无法正常工作

vue.js 基本功能无法正常工作