How to structure my vue 3 app to use an Intersecting Observer?

I am trying to change my header’s background whenever it passes some DOM elements (like <section>).

For this I am using the Intersection Observer. But the vanilla JS version from a lot of examples is not working correctly in my app (in the examples document.querySelectorAll is used which, as in other SO questions is considered as antipattern).

But let’s start from the beginning.
My App.vue structure look’s like:

<template>
  <Header />
  <RouterView />
</template>

Since I am using vue-router, I have a Home.vue view which is structured as:

<template>
  <Hero />
  <NotRelevant Content />
  <NotRelevantContent />
  <NotRelevantContent />
  <Footer />
</template>

So the header is visible on each route (but as of now I only have one).

My should change its background color whenever it intersects with the <Hero /> or the <Footer /> component. Both components have a class="observer" which should trigger the Intersection Observer.

The problem is, that in the <Header /> component the document.querySelectorAll('observer') is undefined. I assume, that not all DOM elements are loaded and that’s why my querySelectorAll is undefined.

My question is, what could I do in this case to solve my problem?

I tried to use this.$nextTick() on the Intersection Observer but with no effect.

I was suggested to use $ref with emmit and props, but how to achieve my desired result, when there are multiple components?

Would like to avoid using vuex to not make this project more complicated.

I found this solution: vue-intersection-observer. Maybe it is worth trying? (As a last resort).

My <Header /> looks like:

<template>
  <header
    class="header fade-in-bg"
    :class="{
      header__scroll: isContrastActive,
    }"
  >
    Logo
  </header>
</template>

<script>

export default {
  data() {
    return {
      isContrastActive: false,
      observer: null,
    }
  },
methods: {
  async activateObserver() {
      this.observer = new IntersectionObserver(
        ([entry]) => {
          if (!entry.isIntersecting) {
            this.isContrastActive = true
          } else {
            this.isContrastActive = false
          }
        },
        { rootMargin: '-5% 0px 0px 0px' }
      )
    const myQuerySelector = 
      document.querySelectorAll('.observer')
        .forEach(el => this.observer.observe(el))

        console.log("myQuerySelector: ", myQuerySelector)
    },
  },
  this.activateObserver()
  },
}
</script>

Hero.vue component:

<template>
  <article class="hero observer">
    HERO
  <article />
<template />

Footer.vue component:

<template>
  <article class="footer observer">
    Footer
  <article />
<template />