Делаю фильтр по нажатию на кнопку должно найти у item категорию которая совпадает с категорией на кнопку, эти элементы оставить а остальные скрыть. Столкнулся с проблемой что в методе setSocialSortBy я сделал массив который содержит Index элементов у которых есть эта категория matchArr = [1,3,5 ...], но не получаеться теперь отфильтровать this.items по этому новому массиву matchArr. Как это можно сделать?
json который приходит с api:
{name: 'title 1', category: 'cat 1'},
{name: 'title 2', category: 'cat 2'},
{name: 'title 3', category: 'cat 1'},
{name: 'title 4', category: 'cat 2'} ...
<button v-for="cat in cats" @click="setCatSortBy(cat)">{{cat}}</button>
<div v-if="items.length > 0">
<div v-for="item in items">{{item.name}}</div>
</div>
<script>
export default {
data() {
items: [],
cats: []
},
created () {
this.fetchItems();
},
methods: {
fetchItems() {
this.loading = true;
fetch("/api/items")
.then(res => res.json())
.then(res => {
this.items = res;
let catArr = [];
this.items.forEach((item) => {
catArr.push(item.category);
});
catArr.filter((value, index, arr) => {
if (arr.indexOf(value) === index) {
this.cats.push(value.toLowerCase());
}
});
});
},
setCatSortBy(name) {
let matchArr = [];
this.items.filter((value, index) => {
if (value.category.toLowerCase() === name.toLowerCase()) {
matchArr.push(index);
}
});
}
}
}
</script>
Думаю, что стоит повторно обратиться к методам фильтрации, которые описаны в этом ответе.
Метод filter()
не изменяет массив к которому применяется, он возвращает новый массив. Т.е. нужно сделать так:
this.items = this.items.filter(...)
Но если вы так сделаете, то из оригинального массива будут удалены отфильтрованные записи. И при дальнейшей фильтрации, этот массив будет "худать", пока не станет пустым.
Именно поэтому вводится промежуточный массив filteredItems
для фильтрации, чтобы оригинальный оставался не тронутым.
Вместо вычисляемого свойства, можно использовать ту же самую функцию в качестве метода. С точки зрения конечного результата, оба подхода делают одно и то же. Но есть важное отличие: вычисляемые свойства кешируются, основываясь на своих реактивных зависимостях. Вычисляемое свойство пересчитывается лишь тогда, когда изменится одна из его реактивных зависимостей. --источник
new Vue({
el: '#app',
data: {
// Модель с записями.
items: [],
// Модель с категориями.
categories: [],
ready: false,
search: {
category: '',
}
},
computed: {
// Вычисляемый список зависит от выбранной категории.
// При изменении категории, список будет отфильтрован.
// Метод filter() создаёт новый массив со всеми элементами,
// прошедшими проверку.
// https://ru.vuejs.org/v2/guide/list.html#Замены-в-массиве
// https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Возвращаемое_значение
filteredItems() {
let category = this.search.category
return category
? this.items.filter(item => item.category === category)
: this.items
}
},
/**
* Используем хук `mounted` для получения записей.
*/
async mounted() {
const response = await this.fetchArticles()
this.items = response.data
this.categories = this.makeCategoryList(this.items)
},
methods: {
// Составляем список всех категорий.
// Нам нужны только уникальные значения, поэтому
// воспользуемся созданием массива ч/з Set.
// За одно и отсортируем.
makeCategoryList(items) {
let cats = new Set()
items.map(item => cats.add(item.category))
return [...cats].sort((a, b) => a.localeCompare(b))
},
fetchArticles() {
this.ready = false
// Импровизация получения данных ч/з ajax.
return new Promise(resolve => {
setTimeout(() => {
this.ready = true
resolve({
// Сортировка: id asc.
data: [{
id: 4,
name: 'Voluptatem enim optio',
category: 'cat 3'
}, {
id: 8,
name: 'Eum praesentium autem',
category: 'cat 2'
}, {
id: 12,
name: 'Voluptatem nihil voluptate',
category: 'cat 1'
}, {
id: 18,
name: 'Debitis illum ex eum',
category: 'cat 3'
}],
meta: {}
})
}, 2000)
})
}
},
})
.form__group {
margin-bottom: 1rem;
}
.form__control {
display: inline-block;
padding: .375rem .75rem;
line-height: 1;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.form__control:focus {
color: #495057;
background-color: #fff;
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, .25);
}
.alert {
padding: 0.75rem 1.25rem;
margin-bottom: 1rem;
border: 1px solid transparent;
}
.alert-info {
color: #2f6473;
background-color: #def2f8;
border-color: #d1edf6;
}
<div id="app">
<div class="filter__box">
<div class="form__group">
<label for="">Фильтровать по категории</label>
<select v-model="search.category" class="form__control">
<option value="">- Категория -</option>
<option v-for="(category, index) in categories" :value="category">{{ category }}</option>
</select>
<!--
Используем вычисляемое свойство, необходимость в кнопке отпадает.
-->
</div>
</div>
<div v-if="!ready" class="alert alert-info">Загрузка записей, ожидайте 2 сек ...</div>
<div v-if="ready && Boolean(filteredItems.length)" class="items">
<template v-for="(item, index) in filteredItems" :key="item.id">
<article class="article">
<h3 class="article__title">#{{ item.id }} {{ item.name }}</h3>
</article>
</template>
</div>
<div v-if="ready && !Boolean(filteredItems.length)" class="alert alert-info">Нет информации для отображения.</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
задача состоит в том чтоб, создать кнопку onlineточнее когда любой пользователь/гость на сайте смотри любой пост, нужно чтоб статус автора был...
В браузерах на андроидах не работает выпадающие меню на сайтеJS код:
Пытаюсь удалить данные с таблицы, и никак не пойму что делаю не такНа сервере все нормально удаляется, а на клиенте обновленную табличку увижу...