Infinite scrolling pagination или бесконечная прокрутка на Vue.js

access_time 2023-08-11 20:32:55

И так, вы пишите приложение и не знаете как сделать пагинацию при прокрутке страницы? Тогда это статья для вас!

При написании кода я использую 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.user_name }}
access_time 2018-11-01 20:15:22

{{ item.text }}