yunohost-admin/app/src/components/LazyRenderer.vue

77 lines
2.1 KiB
Vue
Raw Normal View History

<template>
<div class="lazy-renderer" :style="`min-height: ${fixedMinHeight}px`">
<slot v-if="render" />
</div>
</template>
<script>
export default {
name: 'LazyRenderer',
props: {
unrender: { type: Boolean, default: true },
minHeight: { type: Number, default: 0 },
renderDelay: { type: Number, default: 100 },
unrenderDelay: { type: Number, default: 2000 },
2024-02-24 18:25:12 +01:00
rootMargin: { type: String, default: '300px' },
},
2024-02-24 18:25:12 +01:00
data() {
return {
observer: null,
render: false,
2024-02-24 18:25:12 +01:00
fixedMinHeight: this.minHeight,
}
},
2024-02-24 18:25:12 +01:00
mounted() {
let unrenderTimer
let renderTimer
2021-11-04 17:12:09 +01:00
2024-02-24 18:25:12 +01:00
this.observer = new IntersectionObserver(
(entries) => {
let intersecting = entries[0].isIntersecting
2021-11-04 17:12:09 +01:00
2024-02-24 18:25:12 +01:00
// Fix for weird bug when typing fast in app search or on slow client.
// Intersection is triggered but even if the element is indeed in the viewport,
// isIntersecting is `false`, so we have to manually check this…
// FIXME Would be great to find out why this is happening
if (!intersecting && this.$el.offsetTop < window.innerHeight) {
intersecting = true
}
2021-11-04 17:12:09 +01:00
2024-02-24 18:25:12 +01:00
if (intersecting) {
clearTimeout(unrenderTimer)
// Show the component after a delay (to avoid rendering while scrolling fast)
renderTimer = setTimeout(
() => {
this.render = true
},
this.unrender ? this.renderDelay : 0,
)
2024-02-24 18:25:12 +01:00
if (!this.unrender) {
// Stop listening to intersections after first appearance if unrendering is not activated
this.observer.disconnect()
}
} else if (this.unrender) {
clearTimeout(renderTimer)
// Hide the component after a delay if it's no longer in the viewport
unrenderTimer = setTimeout(() => {
this.fixedMinHeight = this.$el.clientHeight
this.render = false
}, this.unrenderDelay)
}
2024-02-24 18:25:12 +01:00
},
{ rootMargin: this.rootMargin },
)
this.observer.observe(this.$el)
},
2024-03-11 14:43:18 +01:00
beforeUnmount() {
this.observer.disconnect()
2024-02-24 18:25:12 +01:00
},
}
</script>