Files
site/resources/js/Shared/Misc/InfinityScroll.vue

127 lines
4.0 KiB
Vue
Executable File

<template>
<slot v-bind="$attrs" />
<slot v-if="loading" name="loading"
:text="loadText"
>
<div v-if="loading" class="col-span-full flex justify-center">
<svg class="flex-shrink-0 animate-spin h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24"
> <circle class="opacity-25" cx="12"
cy="12" r="10"
stroke="currentColor" stroke-width="4"
></circle><path class="opacity-75" fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path></svg>
</div>
</slot>
</template>
<script>
import { ref, onUpdated, onUnmounted, watch } from 'vue'
import axios from 'axios'
import { usePage } from '@inertiajs/inertia-vue3'
export default {
props: {
nodeElement: Object,
loadText: {
type: String,
default: 'Загрузка ...',
},
nextCursor: { type: String, default: '' },
},
emits: ['fromPagination'],
setup(props, { emit }) {
const cursor = ref(props.nextCursor)
const loading = ref(false)
let installObserver = false
let observer = null
// watch(props, (props) => {
// observer?.disconnect();
// createObserver();
// });
const loadMore = () => {
loading.value = true
if (!cursor.value) {
return Promise.resolve(null)
}
return new Promise((resolve) => {
axios
.get(usePage().url.value, { params: { cursor: cursor.value } })
.then(({ data }) => {
if (data.collections.length) {
cursor.value = data.next
emit('fromPagination', data.collections)
resolve(true)
}
resolve(false)
})
})
}
const createObserver = () => {
if (props.nodeElement) {
const intersectionCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log('isIntersecting')
console.log(props.nodeElement)
removeObserver(entry.target)
loadMore().then((exist) => {
loading.value = false
if (exist) {
createObserver()
}
})
}
})
}
observer = new IntersectionObserver(intersectionCallback, {})
observer.observe(props.nodeElement)
}
}
const removeObserver = (target) => {
observer.unobserve(target)
observer?.disconnect()
}
onUpdated(() => {
if (!installObserver) {
createObserver()
installObserver = true
}
})
onUnmounted(() => {
observer?.disconnect()
})
// onMounted(() => {
// window.addEventListener(
// "scroll",
// debounce((e) => {
// console.log(props.nodeElement);
// let pixelsFromBottom =
// document.documentElement.offsetHeight -
// document.documentElement.scrollTop -
// window.innerHeight;
// if (pixelsFromBottom < props.bottomLine && !loading.value) {
// loading.value = true;
// props.loadMore().finally(() => (loading.value = false));
// }
// }, 200)
// );
// });
return {
loading,
}
},
}
</script>