Vue.js Фильтр по выпадающему списку, если слово найдено в массиве (не только точное совпадение)

#javascript #vue.js #filter

Вопрос:

https://jsfiddle.net/75f3c2po/

Как я могу сделать выше Vue.js фильтр кода по выпадающему списку соответствует всему массиву, даже если другие слова разделены запятыми? Прямо сейчас оно совпадает только в том случае, если type: BMW , но я бы хотел, чтобы оно также показывало карточки, которые могут иметь что-то вроде type: BMW, Ford .

Кроме того, я новичок в Vue, надеялся, что кто-нибудь также сможет показать мне, как я мог бы обновить его, как только select выбран параметр, без необходимости нажимать кнопку «поиск»?

Большое спасибо

Комментарии:

1. Используйте on-change опцию для автоматического обновления ваших фильтров. В вашем случае это будет выглядеть так <select v-model="selectedType" @change="search">

Ответ №1:

Чтобы иметь возможность находить по типу, вы можете разделить строку вашего типа на запятую и проверить, содержит ли массив значение:

       this.searchResult = this.items.filter(function(item) {
        let filtered = true
        if (filterType) {
          filtered = item.type.split(',').includes(filterType)
        }
        if (filtered) {
          if (filterCountry amp;amp; filterCountry.length > 0) {
            filtered = item.country == filterCountry
          }
        }
        if (filtered) {
          if (filterYear amp;amp; filterYear.length > 0) {
            filtered = item.year == filterYear
          }
        }
        return filtered
      })
 

Чтобы иметь возможность выполнять поиск немедленно, вы можете использовать @change обработчик для выбора:

 <select v-model="selectedType" @change="search">
 

Комментарии:

1. Большое вам спасибо!

2. кажется, что фильтрация выполняется только в том случае, если искомое слово является первым в массиве. Можете ли вы помочь мне сделать так, чтобы оно искало слово в любом порядке? Смотрите здесь: jsfiddle.net/9vLhkomn — Спасибо!

3. да, проблема в том, что JS является языком, чувствительным к регистру, и у вас должны быть свои значения в том же регистре. Например, для использования .toLowerCase() метода ( filtered = item.type.split(',').includes(filterType.toLowerCase()) ). Также вы должны удалить пустые пробелы из списка данных или удалить ненужные пробелы, используя .trim() , когда вы разделяете строку запятой. Проверьте это на нашем jsfiddle.net/cqp29d7t/3

4.Большое вам спасибо!

Ответ №2:

Я предоставил фрагмент ниже на основе вашей скрипки.

Изменил ваше searchResults свойство на вычисляемое свойство, чтобы оно автоматически обновлялось при обнаружении изменения в selectedType , selectedCountry или selectedYear .

Чтобы проверить тип, я бы сначала разделил ваш список csv, а затем проверил, существует ли тип в этом массиве. Я сделал это с помощью item.type.split(',').map(x => x.trim()).indexOf(filterType) !== -1;

Убедитесь, что вы понимаете основы Vue и читаете вычисляемые свойства и наблюдатели

 Vue.config.devtools = false;
Vue.config.productionTip = false;

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

      return this.items.filter(function(item) {
        let filtered = true
        if (filterType amp;amp; filterType.length > 0) {
          filtered = item.type.split(',').map(x => x.trim()).indexOf(filterType) !== -1;
        }
        if (filtered) {
          if (filterCountry amp;amp; filterCountry.length > 0) {
            filtered = item.country == filterCountry
          }
        }
        if (filtered) {
          if (filterYear amp;amp; 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/vue/2.5.17/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>

  <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> 

Комментарии:

1. Спасибо! Кажется, что фильтрация выполняется только в том случае, если искомое слово является первым словом в списке, разделенном запятыми. Есть ли способ сделать так, чтобы оно искало слово в любом порядке? Так что, как BMW, Ford и Ford, BMW ?

2. @adamwstl Я добавил a .map(x => x.trim()) , чтобы удалить все пробелы, которые были в элементах массива

3. Спасибо! ценю последующие действия

4. @adamwstl Не все ваши элементы имеют a specialties , поэтому вам также нужно проверить, существует ли оно, т.е. filtered = item.specialties amp;amp; item.specialties.split(',').map(x => x.trim()).indexOf(filterSpecialties) !== -1;

5. Большое вам спасибо!