Последняя версия с сервера прошлого разработчика
This commit is contained in:
126
resources/js/Shared/Misc/InfinityScroll.vue
Executable file
126
resources/js/Shared/Misc/InfinityScroll.vue
Executable file
@@ -0,0 +1,126 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user