Я использую Svelte впервые и пытаюсь понять, как применить фильтрацию к списку, полученному из API. Мой компонент EventsIndex очень прост и включает в себя следующую логику:
import FetchPosts from '../services/postsByType'
import EventCard from '../components/EventCard.svelte'
export let post_type
let events = new FetchPosts( post_type ).get()
let currentCategory = 0
function updateCategory( catId ) {
currentCategory = catId
}
Все работает так, как ожидалось.
Я также использую синтаксис шаблона ожидания для отображения соответствующих данных:
{#await events}
<h1>loading...</h1>
{:then events}
<section class = "grid">
{#each events as event}
<EventCard event = {event} on:filter = {updateCategory}/>
{/each}
</section>
{:catch error}
<p>Something went wrong...</p>
{/await}
Недостающая часть — это реактивный отфильтрованный список. I мысль Я мог бы сделать следующее, но это генерирует ошибку events.map is not a function
, что имеет смысл, поскольку переменная событий будет неразрешенным обещанием при вызове filteredEvents.
$: filteredEvents = () => {
if (currentCategory === 0) return events
return events.filter( event => {
return event.categories !== null
? event.categories.some( cat => cat.id == currentCategory )
: false
})
}
Итак, как мне добавить реактивную функцию filteredEvents, которую я также могу включить в свой шаблон?
@Corrl Не могли бы вы уточнить? Я не уверен, как это сделать...
@Corrl Неважно, я нашел именно то, что вы упомянули. Если вы хотите включить это в качестве ответа, я с радостью приму.
Хорошо, что это решено, и спасибо, что приняли! :) Я только что добавил дополнение, касающееся функции... не связанное с вопросом, но тем не менее подумал, что это может быть полезно.
Фильтрация событий внутри цикла {#each}
должна работать. Если бы функция фильтра была очень короткой, я бы применил ее встроенной.
{#each events.filter(e => e.id === currentId) as event}
Просто как пример. Поскольку в вашем случае функция фильтра более сложна, лучшим вариантом может быть ее перемещение в функцию.
filterEvents(events, currentCategory) {
if (currentCategory === 0) return events
return events.filter( event => {
return event.categories !== null
? event.categories.some( cat => cat.id == currentCategory )
: false
})
}
</script>
...
{#each filterEvents(events, currentCategory) as event}
(Я думаю, вы можете заменить это
return event.categories !== null
? event.categories.some( cat => cat.id == currentCategory )
: false
этим
event?.categories.some( cat => cat.id === currentCategory )
Большое спасибо. Я переключил рефакторинг на event.categories?.some( cat => cat.id == catId )
, но в остальном все идеально.
Также, возможно, стоит отметить, что если бы я сократил его до {#each filterEvents(events) as event}
, список не обновлялся бы при обновлении категории. Но было бы, если бы я сократил до {#each filterEvents(currentCategory) as event}
... кажется, вам нужно передать обновленную переменную в качестве параметра, возможно.
Да, я не думал об изменении currentCategory. На самом деле он должен быть установлен как параметр, поэтому функция срабатывает при изменении, так что это должно быть filterEvents(events, currentCategory)
Ответ будет скорректирован, спасибо за упоминание! (Возможно, вам не нужно передавать события в качестве параметра, потому что они разрешаются и находятся в области видимости, когда функция вызывается в первый раз. Но я бы все же сделал это, думаю, так понятнее...)
Вы пробовали фильтровать события внутри каждого цикла?