<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: 100 }) readonly distance!: number; private observer!: IntersectionObserver; // 'mounted' hook runs after initial render mounted() { const options = { root: this.$refs.scrollContainer as HTMLElement, 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() { 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>