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

后端 未结 7 1249
借酒劲吻你
借酒劲吻你 2020-12-07 20:23

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


    ...
<         


        
相关标签:
7条回答
  • 2020-12-07 20:25

    this does not refresh your component I solved the problem by using Vux create a module for vuex "page"

    export const state = {
        currentScrollY: 0,
    };
    
    export const getters = {
        currentScrollY: s => s.currentScrollY
    };
    
    export const actions = {
        setCurrentScrollY ({ commit }, y) {
            commit('setCurrentScrollY', {y});
        },
    };
    
    export const mutations = {
        setCurrentScrollY (s, {y}) {
           s.currentScrollY = y;
        },
    };
    
    export default {
        state,
        getters,
        actions,
        mutations,
    };
    
    

    in App.vue :

    created() {
        window.addEventListener("scroll", this.handleScroll);
      },
      destroyed() {
        window.removeEventListener("scroll", this.handleScroll);
      },
      methods: {
        handleScroll () {
          this.$store.dispatch("page/setCurrentScrollY", window.scrollY);
          
        }
      },
    

    in your component :

      computed: {
        currentScrollY() {
          return this.$store.getters["page/currentScrollY"];
        }
      },
    
      watch: {
        currentScrollY(val) {
          if (val > 100) {
            this.isVisibleStickyMenu = true;
          } else {
            this.isVisibleStickyMenu = false;
          }
        }
      },
    

    and it works great.

    0 讨论(0)
  • 2020-12-07 20:27

    I know this is an old question, but I found a better solution with Vue.js 2.0+ Custom Directives: I needed to bind the scroll event too, then I implemented this.

    First of, using @vue/cli, add the custom directive to src/main.js (before the Vue.js instance) or wherever you initiate it:

    Vue.directive('scroll', {
      inserted: function(el, binding) {
        let f = function(evt) {
          if (binding.value(evt, el)) {
            window.removeEventListener('scroll', f);
          }
        }
        window.addEventListener('scroll', f);
      }
    });
    

    Then, add the custom v-scroll directive to the element and/or the component you want to bind on. Of course you have to insert a dedicated method: I used handleScroll in my example.

    <my-component v-scroll="handleScroll"></my-component>
    

    Last, add your method to the component.

    methods: {
      handleScroll: function() {
        // your logic here
      }
    }
    

    You don’t have to care about the Vue.js lifecycle anymore here, because the custom directive itself does.

    0 讨论(0)
  • 2020-12-07 20:34

    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!

    0 讨论(0)
  • 2020-12-07 20:35

    I think the best approach is just add ".passive"

    v-on:scroll.passive='handleScroll'
    
    0 讨论(0)
  • 2020-12-07 20:39

    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');
        }
      },
    
      created() {
        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

    0 讨论(0)
  • 2020-12-07 20:40

    Here's what works directly with Vue custom components.

     <MyCustomComponent nativeOnScroll={this.handleScroll}>
    

    or

    <my-component v-on:scroll.native="handleScroll">
    

    and define a method for handleScroll. Simple!

    0 讨论(0)
提交回复
热议问题