Vue 3 Performance Optimization with Virtual Scrolling
Implement virtual scrolling in a Vue 3 app to display large lists of items efficiently on mobile devices, reducing the DOM footprint and improving FPS.
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
// Register your global components here, if any.
app.mount('#app');
This is the entry point of a Vue 3 application where the App component, which will contain the virtual scrolling logic, is initialized and mounted to the DOM.
<template>
<div class="virtual-scroll" ref="scrollContainer">
<div v-for="item in visibleItems" :key="item.id" class="list-item">
<!-- Your item component/content here -->
{{ item.content }}
</div>
</div>
</template>
<script setup>
import { ref, onMounted, computed, watch } from 'vue';
import { useVirtualScrolling } from '@/composables/useVirtualScrolling';
const props = defineProps({
items: Array,
itemHeight: Number
});
const scrollContainer = ref(null);
const { start, end, visibleItems } = useVirtualScrolling(scrollContainer, props.items, props.itemHeight);
onMounted(() => {
const resizeObserver = new ResizeObserver(() => {
// Recalculate visible items on container resize
start.value = calculateStartIndex(scrollContainer.value.scrollTop, props.itemHeight);
end.value = calculateEndIndex(start.value, scrollContainer.value.clientHeight, props.itemHeight, props.items.length);
});
resizeObserver.observe(scrollContainer.value);
});
</script>
Vue 3 component template and script setup for virtual scrolling. The 'useVirtualScrolling' composable is a custom hook that handles the calculations for visible items based on scroll position. 'visibleItems' is a computed property that depends on the 'start' and 'end' reactive references, which represent the range of items to display.
import { ref, computed, watch } from 'vue';
export function useVirtualScrolling(containerRef, items, itemHeight) {
const start = ref(0);
const end = ref(0);
const visibleItems = computed(() => items.slice(start.value, end.value));
const handleScroll = () => {
const scrollTop = containerRef.value.scrollTop;
start.value = calculateStartIndex(scrollTop, itemHeight);
end.value = calculateEndIndex(start.value, containerRef.value.clientHeight, itemHeight, items.length);
};
watch(containerRef, (newValue, oldValue) => {
if (newValue) {
newValue.addEventListener('scroll', handleScroll);
}
if (oldValue) {
oldValue.removeEventListener('scroll', handleScroll);
}
});
return { start, end, visibleItems };
}
function calculateStartIndex(scrollTop, itemHeight) {
return Math.floor(scrollTop / itemHeight);
}
function calculateEndIndex(startIndex, clientHeight, itemHeight, totalItems) {
const endIndex = startIndex + Math.ceil(clientHeight / itemHeight);
return Math.min(endIndex, totalItems);
}
Definition of the 'useVirtualScrolling' composable function that is responsible for managing virtual scrolling. It creates reactive references for start and end indices, computed property for visible items, and sets up a scroll event listener to recompute visible items as the user scrolls through the container.