Iulia Mihet
Iulia Mihet

Reputation: 700

Watch window.scrollY changes in Vuejs

I have a very simple app, that has 2 components: the App.vue and another component, Home.vue where I hold the rest of the structure of the app: a sticky header and some sections with anchors to scroll to.

I want to apply a class to the sticky header to minimize the logo while the page is scrolled. So I thought I'd watch for any changes in window.scrollY. So if scrollY is greater than 0, apply some class that minimizes the logo.

I tried to listen to scroll events in my component, but that didn't go very far. In this discussion here, a very good solution is provided, but I don't know where to place the scroll event. https://github.com/vuejs/Discussion/issues/324

So, I thought the most fitting solution would be to create a data property, assign it the window.scrollY figure and then watch for changes in its value. Unfortunately, the watcher is never triggered. So now I'm stuck. The code is:

data () {
return {
  ...
  windowTop: window.top.scrollY
 }
}
...
watch: {
 windowTop: {
  immediate: true,
  handler (newVal, oldVal) {
    console.log(newVal, oldVal);
  },
 }
}

Any ideas of what I might be doing wrong?

Upvotes: 14

Views: 38659

Answers (5)

tony19
tony19

Reputation: 138696

window properties can't be used reactively like that. Instead, you'd have to listen to the window's scroll event and respond accordingly:

mounted() {
  window.addEventListener("scroll", this.onScroll)
},
beforeDestroy() {
  window.removeEventListener("scroll", this.onScroll)
},
methods: {
  onScroll(e) {
    this.windowTop = window.top.scrollY /* or: e.target.documentElement.scrollTop */
  }
}

Edit Watching scrollTop in Vue

Upvotes: 38

Shubham Dubey
Shubham Dubey

Reputation: 123

I was trying to do something where I just have to call a variable or function to get the window scroll position in any component. So in order to achieve that I end up using mixins. Here is my code. I am using nuxt.

Inside plugin create a file eg. scroll-position.js

import Vue from 'vue'

Vue.mixin({
    data() {
        return {
            scrollPosition: window.scrollY
        }
    },
    methods: {
        get_scroll_position() {
            window.addEventListener('scroll', () => {
                this.scrollPosition = window.scrollY;
            });
            return this.scrollPosition
        }
    }
})

In nuxt.config.js

plugins:['@/plugins/scroll-position.js']

Now you can use get_scroll_position() in any component you want Something like this

:class="{'header_sticky':get_scroll_position()>=80}"

Upvotes: 0

LastM4N
LastM4N

Reputation: 2240

For me none of the above worked.

I had to pass true as 3rd parameter in add/remove scroll listener:

mounted() {
  window.addEventListener("scroll", this.onScroll, true)
},
beforeDestroy() {
  window.removeEventListener("scroll", this.onScroll, true)
},
methods: {
  onScroll(e) {
    this.windowTop = e.target.scrollTop;
  }
}

3rd parameter: You should be able to attach a document-level listener with a third parameter of true to capture the scroll events on all elements. Here's what that looks like:

document.addEventListener('scroll', function(e){ }, true);

The true at the end is the important part, it tells the browser to capture the event on dispatch, even if that event does not normally bubble, like change, focus, and scroll.

Upvotes: 13

KitKit
KitKit

Reputation: 9583

2020 Updated:

Use @scroll.passive to watch scroll of any element in component:

Example:

Template

<div class="room_message-stream" @scroll.passive="handleScroll">
      <ul class="room_message-stream__list">
        <li class="room_message-stream__list-item">...</li>
      </ul>
</div>

Methods:

handleScroll (e) {
  var scrollPos = e.target.scrollTop
}

Upvotes: 6

Taha Paksu
Taha Paksu

Reputation: 15616

You can use the mounted() method to add your event listener to the window object like this:

var p = new Vue({
   el: "#app",
   data(){
      return {
          windowTop: 0
      };
   },
   mounted()
   {
       var that = this;
       window.addEventListener("scroll", function(){
           that.windowTop = window.scrollY;
       });
   },
   template: "<div style='height: 250vh'><div style='position: fixed; right: 0; top: 0'>{{windowTop}}</div></div>"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Upvotes: 0

Related Questions