<template> <div ref="scrollContainer"> <slot /> <div ref="sentinel" style="height: 1px"></div> </div> </template> <script lang="ts"> import { Component, Emit, Prop, Vue } from "vue-facing-decorator"; @Component export default class InfiniteScroll extends Vue { @Prop({ default: 200 }) readonly distance!: number; private observer!: IntersectionObserver; private isInitialRender = true; updated() { if (!this.observer) { const options = { root: null, rootMargin: `0px 0px ${this.distance}px 0px`, threshold: 1.0, }; this.observer = new IntersectionObserver( this.handleIntersection, options, ); this.observer.observe(this.$refs.sentinel as HTMLElement); } } // 'beforeUnmount' hook runs before unmounting the component beforeUnmount() { if (this.observer) { this.observer.disconnect(); } } @Emit("reached-bottom") handleIntersection(entries: IntersectionObserverEntry[]) { const entry = entries[0]; if (entry.isIntersecting) { return true; } return false; } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped></style>