Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to listen to the window scroll event in a VueJS component?

I want to listen to the window scroll event in my Vue component. Here is what I tried so far:

<my-component v-on:scroll="scrollFunction">     ... </my-component> 

With the scrollFunction(event) being defined in my component methods but it doesn't seem to work.

Anyone has any idea how to do this?

Thanks!

like image 602
jeerbl Avatar asked Aug 22 '17 15:08

jeerbl


People also ask

How do I trigger an event at the Vue?

We can trigger events on an element with Vue. js by assigning a ref to the element we want to trigger events for. Then we can call methods on the element assigned to the ref to trigger the event.

How do I get the scroll position of an element?

To get or set the scroll position of an element, you follow these steps: First, select the element using the selecting methods such as querySelector() . Second, access the scroll position of the element via the scrollLeft and scrollTop properties.

What is $V in Vue?

$v is an object that calls vuelidate (at the time of writing the comment, supported in version Vue. js 2.0), which is intended to check every input, which is made in a non-html form.


2 Answers

Actually I found a solution. I add an event listener on the scroll event when the component is created and remove the event listener when the component is destroyed.

export default {   created () {     window.addEventListener('scroll', this.handleScroll);   },   destroyed () {     window.removeEventListener('scroll', this.handleScroll);   },   methods: {     handleScroll (event) {       // Any code to be executed when the window is scrolled     }   } } 

Hope this helps!

like image 143
jeerbl Avatar answered Sep 17 '22 18:09

jeerbl


In my experience, using an event listener on scroll can create a lot of noise due to piping into that event stream, which can cause performance issues if you are executing a bulky handleScroll function.

I often use the technique shown here in the highest rated answer, but I add debounce on top of it, usually about 100ms yields good performance to UX ratio.

Here is an example using the top-rated answer with Lodash debounce added:

import debounce from 'lodash/debounce';  export default {   methods: {     handleScroll(event) {       // Any code to be executed when the window is scrolled       this.isUserScrolling = (window.scrollY > 0);       console.log('calling handleScroll');     }   },    mounted() {     this.handleDebouncedScroll = debounce(this.handleScroll, 100);     window.addEventListener('scroll', this.handleDebouncedScroll);   },    beforeDestroy() {     // I switched the example from `destroyed` to `beforeDestroy`     // to exercise your mind a bit. This lifecycle method works too.     window.removeEventListener('scroll', this.handleDebouncedScroll);   } } 

Try changing the value of 100 to 0 and 1000 so you can see the difference in how/when handleScroll is called.

BONUS: You can also accomplish this in an even more concise and reuseable manner with a library like vue-scroll. It is a great use case for you to learn about custom directives in Vue if you haven't seen those yet. Check out https://github.com/wangpin34/vue-scroll.

This is also a great tutorial by Sarah Drasner in the Vue docs: https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html

For Vue 3 users

In vue3 you should use unmounted or beforeUnmount, instead of beforeDestroy.

Lifecycle hook beforeDestroy is not emitted in Vue3

like image 28
agm1984 Avatar answered Sep 20 '22 18:09

agm1984