Custom LazyLoad Component
Let’s further improve the lazy load functionality.
We'll cover the following...
We’ve just covered how we can lazy load a component with an Intersection Observer. It’d be admittedly tedious to add the same logic everywhere we want to lazy load components, though, especially if there are a few of them.
Custom component
Let’s create a component that will make it easier to lazy load components when the browser is idle, or if a user scrolls close to the component to render.
Press + to interact
// LazyLoad.vue<script>import { ref, watch, onMounted } from 'vue'import { useIntersectionObserver } from '@/composables'const isClient = typeof window !== 'undefined'const loadOnIntersect = ({ containerRef, loadComponent, observerOptions }) => {const { isIntersecting } = useIntersectionObserver(containerRef,observerOptions)watch(isIntersecting, isIntersecting => {isIntersecting && loadComponent()})}const loadOnIdle = ({ loadComponent, idleTimeout }) => {// Load component immediately if not in the browser environment// or if one of the necessary APIs is not supportedif(!isClient || Dat!('requestIdleCallback' in window || !('requestAnimationFrame' in window))){loadComponent()return}// Load the component when the browser is free or schedule it// after the timeout is reachedrequestIdleCallback(() => {requestAnimationFrame(loadComponent)},{ timeout: idleTimeout })}export default {props: {idleTimeout: {type: Number,default: 3000,},onIdle: {type: Boolean,default: false,},onVisible: {type: [Object, Boolean],default: null,},},setup(props, { slots, emit}){const isComponentLoaded = ref(false)const containerRef = ref(null)let loadType = 'onIdle'if(props.onIdle) loadType = 'onIdle'else if(props.onVisible) loadType = 'onVisible'const config = {onIdle: loadOnIdle,onVisible: loadOnIntersect,}const loadComponent = () => {isComponentLoaded.value = trueemit('loaded')}// Call appropriate handlerconfig[loadType]({containerRef,loadComponent,idleTimeout: props.idleTimeout,observerOptions: typeof props.onVisible === 'object' ? props.onVisible : {},})/*** If component is to be loaded then pass through slots* Otherwise, render a div with a ref that is needed for* the Intersection Observer*/return() =>isComponentLoaded.value ? slots.default() : < div ref = { containerRef }/>},}</script>
The LazyLoad
component accepts the onVisible
, onIdle
, and idleTimeout
props. The onVisible
prop ...