#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/34.Большое вам спасибо!
Ответ №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. Большое вам спасибо!