И так, вы пишите приложение и не знаете как сделать пагинацию при прокрутке страницы? Тогда это статья для вас!
При написании кода я использую 3 версию Vue.js и Composition API. Если кто-то не знаком с Composition API то лучше почитать документацию.
Создаём компонент пагинации InfiniteScrollingPagination со следующим кодом:
<script setup>
import {onMounted, onUnmounted, ref} from "vue";
const emit = defineEmits(['loadMore']);
const props = defineProps({
cursor: String
});
onMounted(() => {
window.addEventListener("scroll", handleScroll)
})
onUnmounted(() => {
window.removeEventListener("scroll", handleScroll)
})
const scrollWrap = ref(null);
const handleScroll = (e) => {
let element = scrollWrap.value;
if(
props.cursor &&
element.getBoundingClientRect().y <= -20
) {
emit('loadMore');
}
}
</script>
<template>
<div class="list-wrap" ref="scrollWrap">
<slot></slot>
</div>
</template>
<style scoped>
</style>
Теперь разберём что мы имеем.
Создаём событие компонента loadMore, которое будем вызывать в тот момент, когда дойдём до конца страницы.
Объявляем свойство компонента cursor. В целом, свойство cursor - это признак, говорящий есть ли ещё записи для загрузки. Почему cursor спросите вы? Потому что я использую на бекенде Laravel и cursorPaginate для пагинации, о которой подробнее можно прочитать в документации. Вы можете назвать свойство по другому и передавать свой признак в зависимости от вашей реализации пагинации.
Создаём слушатель handleScroll события scroll нашей страницы.
Создаём ref-объект scrollWrap, который будет ссылаться на обёртку контента в шаблоне нашего компонента.
В слушателе handleScroll проверяем через свойство cursor надо ли ещё подгружать записи и проверяем позицию нашего scrollWrap с помощью getBoundingClientRect который возвращает размеры и позицию нашего scrollWrap относительно окна браузера / viewport . В моём случае если ось Y меньше или равна -20, оптимально вызывать событие loadMore. У вас могут быть совсем другие значения, но смысл думаю вы уловили.
При вызове события loadMore, в вашем родительском компоненте должен сработать слушатель, с вашей реализацией пагинации. У меня в шаблоне родительского компонента это выглядит примерно так:
<InfiniteScrollingPagination :cursor="state.postList.cursor" @load-more="loadPostList">
<PostListComponent :items="state.postList.items"></PostListComponent>
</InfiniteScrollingPagination>
На этом всё!
Надеюсь всё понятно и кому-то поможет.
А если остались вопрос - пишите их в комментарии, с удовольствием отвечу!
{{ item.text }}