如何在VueJS组件中监听窗口滚动事件?

jee*_*rbl 35 javascript vue.js vuejs2

我想听听Vue组件中的窗口滚动事件.这是我到目前为止尝试的内容:

<my-component v-on:scroll="scrollFunction">
    ...
</my-component>
Run Code Online (Sandbox Code Playgroud)

随着scrollFunction(event)正在我的组件方法来定义,但它似乎并没有工作.

任何人都知道如何做到这一点?

谢谢!

jee*_*rbl 92

其实我找到了解决方案.我在scroll创建组件时在事件上添加了一个事件监听器.此外,请确保在销毁组件时删除事件侦听器.

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

希望这可以帮助!

  • @AlexanderKim正确.即使组件不再可见,它也会继续触发您提供的方法. (4认同)
  • 如果不被摧毁会怎样?它适用于所有页面吗? (3认同)
  • @AlexanderKim 如果您使用的是保持活动组件,并且您希望它在不活动时停止,您应该使用停用而不是销毁,并使用激活而不是创建。这也应该使用mounted而不是created,因为即使创建也不能保证被安装。 (3认同)
  • 对于 Nuxt,您需要使用 beforeMount 和 beforeDestory,因为它无法访问 window 属性。/sf/ask/3312898361/ (3认同)
  • 我也面临同样的问题。HandleScroll 方法中没有任何反应。对于 vue js 建议任何方法。 (2认同)
  • 更新:不推荐使用“destroyed()”生命周期挂钩,使用“unmounted()” (2认同)

Loi*_*ilo 8

我多次需要此功能,因此我已将其提取到mixin 中。它可以像这样使用:

import windowScrollPosition from 'path/to/mixin.js'

new Vue({
  mixins: [ windowScrollPosition('position') ]
})
Run Code Online (Sandbox Code Playgroud)

这会position在 Vue 实例上创建一个响应式属性(可以随意命名)。该属性包含作为[x,y]数组的窗口滚动位置。

随意使用这个 CodeSandbox 演示

这是mixin的代码。它经过了彻底的评论,因此了解它的工作原理应该不会太难:

function windowScrollPosition(propertyName) {
  return {
    data() {
      return {
        // Initialize scroll position at [0, 0]
        [propertyName]: [0, 0]
      }
    },
    created() {
      // Only execute this code on the client side, server sticks to [0, 0]
      if (!this.$isServer) {
        this._scrollListener = () => {
          // window.pageX/YOffset is equivalent to window.scrollX/Y, but works in IE
          // We round values because high-DPI devies can provide some really nasty subpixel values
          this[propertyName] = [
            Math.round(window.pageXOffset),
            Math.round(window.pageYOffset)
          ]
        }

        // Call listener once to detect initial position
        this._scrollListener()

        // When scrolling, update the position
        window.addEventListener('scroll', this._scrollListener)
      }
    },
    beforeDestroy() {
      // Detach the listener when the component is gone
      window.removeEventListener('scroll', this._scrollListener)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Fed*_*tti 7

我知道这是一个老问题,但我找到了Vue.js 2.0+ 自定义指令的更好解决方案:我也需要绑定滚动事件,然后我实现了这个。

首先,使用@vue/cli,将自定义指令添加到src/main.js(在 Vue.js 实例之前)或您启动它的任何地方:

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

然后,将自定义v-scroll指令添加到要绑定的元素和/或组件。当然你必须插入一个专用的方法:我handleScroll在我的例子中使用过。

<my-component v-scroll="handleScroll"></my-component>
Run Code Online (Sandbox Code Playgroud)

最后,将您的方法添加到组件中。

methods: {
  handleScroll: function() {
    // your logic here
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里您不必再关心 Vue.js 生命周期,因为自定义指令本身就是如此。


kus*_*lvm 6

您的要求是在组件上,但是最后增加了主体,而不是组件。当然,您也可以在特定元素上执行此操作,但是,嘿...这就是直接与Vue自定义组件一起使用的功能。

 <MyCustomComponent nativeOnScroll={this.handleScroll}>
Run Code Online (Sandbox Code Playgroud)

要么

<my-component v-on:scroll.native="handleScroll">
Run Code Online (Sandbox Code Playgroud)

并为handleScroll定义一个方法。简单!

  • “nativeOnScroll”到底是什么? (11认同)
  • 使用Vue自定义组件时,如果要启动任何本机事件,请说-单击,滚动,更改-您需要对其使用本机。onChange或onScroll将不起作用。举一个简单的例子,想像一个`&lt;MyButton v-on:click =“ thisWontWork” /&gt;`,但是`&lt;MyButton v-on:click.native =“ thisWorks” /&gt;` (2认同)

小智 6

我认为最好的方法是添加“.passive”

v-on:scroll.passive='handleScroll'
Run Code Online (Sandbox Code Playgroud)


agm*_*984 5

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 你真的需要“lodash”吗?在“handleScroll”函数中使用“setTimeout”并清除超时ID(如果它不为空)就可以解决问题。无论如何,两者都可以工作,但我们可以通过两行代码避免使用该库 (3认同)