0

I'm trying to use the composition API to create a function that can hide the navbar when scrolling up and show it when scrolling down. I already have this function in vanilla JS, but in Vue3 I'm having difficulty bringing it into the DOM.

In vanilla JS:

let prevScrollpos = window.pageYOffset;
window.onscroll = function () {
  console.log('scrolling')
  let currentScrollPos = window.pageYOffset;
  if (prevScrollpos > currentScrollPos) {
    // @ts-ignore
    document.getElementById("navbar").style.top = "0";
  } else {
    // @ts-ignore
    document.getElementById("navbar").style.top = "-65px";
  }
  prevScrollpos = currentScrollPos;
}

My issue is, in Vue3, I can't seem to register some simple scroll function such as pageYOffset more than once. I am not having any success with the @scroll="function" directive, or with event listeners. At the moment, I'm attempting to use a directive to see the DOM at the base layer, but I don't know how to continually track the scroll position this way either. I would be happy for a fix using a directive but I would also be glad to have a solution that existed just within the Navbar.vue, the Homepage.vue, or the App.vue.

So how do I make Vue3 see the window's scroll position using the Composition API?

David Scholz
  • 8,421
  • 12
  • 19
  • 34

1 Answers1

0

Alright, so I actually found an answer with the help of my instructor and this post. I didn't realize that because my parallax scrolling effect (which isn't shown above) had all the scrolling happening in the main tag, it meant that the window never saw any scrolling. Also, I didn't realize that putting this onscroll effect in an onMounted hook worked just fine to interact with the DOM in the Composition API, probably because of the first problem. I fixed it, and now my finished code looks like this.

    onMounted(() => {
      let main = document.querySelector("main");
      let prevScrollpos = main.scrollTop;
      let nav = document.querySelector(".navbar");
      main.onscroll = function () {
        let currentScrollPos = main.scrollTop;
        if (prevScrollpos > currentScrollPos) {
          // @ts-ignore
          nav.classList.add("navbar_hidden");
        } else {
          // @ts-ignore
          nav.classList.remove("navbar_hidden");
        }
        prevScrollpos = currentScrollPos;
      };
    });

Because its now in the main tag, I couldn't use PageYOffset so I changed that to scrollTop. Here's the CSS. All this is in the Navbar.vue component

.navbar {
  background: $dark;
  transform: translate3d(0, 0, 0);
  transition: all 0.2s ease-out;
}

.navbar_hidden {
  transform: translate3d(0, -100%, 0);
}

Thus, my not-so-thrilling saga comes to a close.