I'm trying to set up an IntersectionObserver
on my feedback section, which has an autoplay feature. I use SwiperJS in Vue 3. First check if the section is visible and then start autoplay, otherwise, I stop it. However, the observer continues to work endlessly, which might take up resources. I tried adding observer.disconnect()
in the if
statement, but then it stops observing after scrolling to the section for the first time.
// template
<Swiper
class="swiper"
v-bind="swiperOptions"
ref="target"
@swiper="onSwiper">
<SwiperSlide class="swiper__slide">
...
</SwiperSlide>
</Swiper>
// script
import { watchEffect, ref } from 'vue';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Autoplay } from 'swiper/modules';
const swiperOptions = {
modules: [Autoplay],
autoplay: {
delay: 4000,
disableOnInteraction: true,
},
loop: true,
};
const target = ref<HTMLElement | null>(null);
const isVisible = ref(false);
const onSwiper = swiper => {
const observer = new IntersectionObserver(
([entry]) => {
isVisible.value = entry.isIntersecting;
if (isVisible.value) {
swiper.autoplay.start();
} else {
swiper.autoplay.stop();
}
},
{ threshold: 0 }
);
if (target.value) {
observer.observe(target.value);
}
};
I get the error 'Uncaught (in promise) TypeError: Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'.'
// This approach also didn't work.
if (isVisible.value) {
swiper.autoplay.start();
observer.disconnect();
} else {
swiper.autoplay.stop();
observer.observe(target.value);
}
Looking for a possible solution.
The issue was in the placement of the ref attribute. Initially, I had placed ref="target"
on the <Swiper>
component itself, which was causing the problem. The correct approach is to put ref="target"
on the wrapper instead, in my case it's a <section>
.