[Vuejs]-Unable to use IntersectionObserver in Vue

0👍

The code you provided seems to mostly work but that’s not how we do things in Vue. In Vue you should use template refs to reference components instead of using querySelector and you should also use refs to change classes in the template instead of directly modifying the DOM yourself (vue’s reactivity system can’t track the changes you make manually yourself and might overwrite them at any moment). To make all of the above easier we will need to make the section it’s own component.

App.vue:

<template>
  <div style="height: 1000px; background: red"></div>
  <Section>
    <h1>Title</h1>
    <p>Some text</p>
  </Section>
  <Section>
    <h2>More text</h2>
  </Section>
</template>

<style scoped>
* {
  background-color: 131313;
  padding: 0;
  margin: 0;
}
</style>

<script setup>
import Section from './Section.vue'

</script>

Section.vue:

<template>
  <section class="hidden" :class="{show}" ref="section">
    <slot></slot>
  </section>
</template>

<style sciped>
section {
  display: grid;
  place-items: center;
  align-content: center;
  min-height: 100vh;
}
.hidden {
  opacity: 0.5;
  transition: all 2s;
}
.show {
  opacity: 1;
  background: blue;
}
</style>

<script setup>
import { onMounted, ref } from "vue";
  
const section = ref(null);
const show = ref(false);

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    console.log(entry);
    show.value = entry.isIntersecting;
  });
});

onMounted(() => observer.observe(section.value));
</script>

Live demo: Vue SFC Playground

In the example I also used the isIntersecting property to determine if the element is intersecting instead of using the ratio.

Leave a comment