Seamless Infinite Scroll Experience with Vue 3: The Art of Loading Without Interruptions

Seamless Infinite Scroll Experience with Vue 3: The Art of Loading Without Interruptions

Imagine this: you’re browsing through a mesmerizing collection of resources—perhaps articles, code snippets, or design templates. You keep scrolling, and the content flows effortlessly, with more items loading as if by magic, without you having to lift a finger. Welcome to the world of infinite scroll, a feature that has become essential in modern web applications. But behind this fluid experience lies a meticulously orchestrated setup. Let’s dive into the inner workings of a Vue 3 infinite scroll, revealing the artistry behind the code.


The Vision: An Endless Stream of Content

Our journey begins with app-items.vue, the component responsible for rendering a grid of resources. These items load incrementally, page by page, as the user scrolls down, delivering a seamless browsing experience. But how do we ensure everything loads smoothly, with no jarring pauses or awkward reloads?

The answer lies in a carefully constructed system, where data is fetched incrementally, loading states are managed with grace, and high-performance rendering is prioritized.


The Setup: Tracking State and Fetching Data

At the heart of our infinite scroll lies a series of reactive variables. These keep track of loaded items, the current page number, loading states, and whether there are more items to load:

const items_loaded = ref([]);
const current_page = ref(0); // Track the current page
const isLoading = ref(false); // Is data being fetched?
const has_more = ref(true); // Are there more items to load?

Next, we have the fetchItems function, our data-fetching powerhouse. It’s designed to fetch items from a store, appending them to our items_loaded array while updating our loading state:

const fetchItems = async (page = 1) => {
    if (isLoading.value || !has_more.value) return; // Prevent multiple requests

    isLoading.value = true; // Set loading state
    
    let items = await props.__store.getItems({
        tag_id: selected_tag.value?.id || 0,
        page
    });

    if (!items.length) has_more.value = false; // No more items to load
    else items_loaded.value = [...items_loaded.value, ...items]; // Append items

    isLoading.value = false; // Reset loading state
};

The function is smart: it only fetches data if more items are available and ensures there are no redundant requests. When new items are loaded, we run nextTick() to highlight any code blocks with highlight.js, ensuring our content remains beautifully formatted.


2130+ FREE RESOURCES FOR DEVELOPERS!! ❤️😍🥳 (updated daily)
1400+ Free HTML Templates
310+ Free News Articles
61+ Free AI Prompts
282+ Free Code Libraries
37+ Free Code Snippets & Boilerplates for Node, Nuxt, Vue, and more!
25+ Free Open Source Icon Libraries
Visit dailysandbox.pro for free access to a treasure trove of resources!

Triggering More Data: The Infinite Scroll Mechanism

Our infinite scroll experience wouldn’t be complete without the infinite-scroller.vue component. This component uses an Intersection Observer to detect when the user reaches the end of the content, signaling our app to load more items:

onMounted(() => {
    const observer = new IntersectionObserver((entries) => {
        let entry = entries[0];
        if (entry.isIntersecting) emits('infinite'); // Emit event when in view
    }, { root: null, rootMargin: '0px', threshold: 1.0 });

    observer.observe(end_of_scroller.value); // Observe the end of the scroller
});

Here, the Intersection Observer acts as our watchful sentinel, observing the end_of_scroller element. When this element enters the viewport, an 'infinite' event is emitted, triggering loadMoreItems in app-items.vue. This function increments the current page and fetches the next batch of items:

const loadMoreItems = async () => {
    if (isLoading.value) return; // Avoid fetching if already loading
    current_page.value++; // Increment page
    await fetchItems(current_page.value); // Fetch next batch
};

Elegant UI: Feedback for the User

Loading states and visual feedback are crucial for a polished user experience. We display a spinner while items are loading and a friendly message when there’s no more content:

<div v-if="isLoading" class="loading-text">
    <div class="spinner-border" />
</div>
<div v-if="!has_more" class="no-more-items">
    No more items to load.
</div>

These subtle details keep the user engaged and informed, creating a fluid and enjoyable browsing experience.


The Complete Flow: Putting It All Together

Our infinite scroll system is a masterclass in balancing performance and user experience. As the user scrolls, items load dynamically, the UI stays responsive, and the Intersection Observer ensures everything runs efficiently. Here’s the magic in action:

  1. User Scrolls: As the user scrolls and the end_of_scroller comes into view, an event is emitted to load more items.
  2. Data Fetching: The fetchItems function pulls the next batch of items, appending them to items_loaded.
  3. Graceful UI: A loading spinner appears while items are fetched, and a message signals when there’s nothing left to load.

A Love Letter to Infinite Scroll

Infinite scroll isn’t just a feature; it’s an experience. It’s about creating a journey where content flows effortlessly, and the user never has to think about loading the next page. It’s the small details, like managing loading states and using an Intersection Observer, that elevate the experience from functional to delightful.

So, the next time you scroll through a beautifully crafted interface, think of the orchestrated dance behind the scenes—a dance that makes the endless scroll feel as magical as it does. And remember, as developers, we’re the ones who choreograph that magic, one line of code at a time.

For more tips on web development, check out DailySandbox and sign up for our free newsletter to stay ahead of the curve!