Javascript 如何在 VueJS 组件中监听窗口滚动事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45822150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to listen to the window scroll event in a VueJS component?
提问by jeerbl
I want to listen to the window scroll event in my Vue component. Here is what I tried so far:
我想在我的 Vue 组件中收听窗口滚动事件。这是我到目前为止尝试过的:
<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.
随着scrollFunction(event)正在我的组件方法来定义,但它似乎没有工作。
Anyone has any idea how to do this?
任何人都知道如何做到这一点?
Thanks!
谢谢!
回答by jeerbl
Actually I found a solution. I add an event listener on the scrollevent when the component is created and remove the event listener when the component is destroyed.
其实我找到了解决办法。我在scroll创建组件时在事件上添加一个事件侦听器,并在组件销毁时删除事件侦听器。
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!
希望这可以帮助!
回答by kushalvm
Here's what works directly with Vue custom components.
以下是直接与 Vue 自定义组件配合使用的内容。
<MyCustomComponent nativeOnScroll={this.handleScroll}>
or
或者
<my-component v-on:scroll.native="handleScroll">
and define a method for handleScroll. Simple!
并为 handleScroll 定义一个方法。简单的!
回答by agm1984
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 handleScrollfunction.
根据我的经验,在滚动上使用事件侦听器会由于管道进入该事件流而产生大量噪音,如果您正在执行庞大的handleScroll功能,这可能会导致性能问题。
I often use the technique shown here in the highest rated answer, but I add debounce on top of it, usually about 100msyields good performance to UX ratio.
我经常使用评分最高的答案中显示的技术,但我在其之上添加了去抖动,通常会100ms产生良好的性能与 UX 比率。
Here is an example using the top-rated answer with Lodash debounce added:
这是一个使用评分最高的答案并添加了 Lodash 去抖动的示例:
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 100to 0and 1000so you can see the difference in how/when handleScrollis called.
尝试改变的值100,以0和1000,所以你可以看到如何/当差handleScroll被调用。
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.
奖励:您还可以使用像vue-scroll. 如果您还没有看过 Vue 中的自定义指令,那么这是一个很好的用例。查看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
这也是 Sarah Drasner 在 Vue 文档中的一个很棒的教程:https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html
回答by Loilo
I've been in the need for this feature many times, therefore I've extracted it into a mixin. It can be used like this:
我多次需要此功能,因此我已将其提取到mixin 中。它可以像这样使用:
import windowScrollPosition from 'path/to/mixin.js'
new Vue({
mixins: [ windowScrollPosition('position') ]
})
This creates a reactive positionproperty (can be named whatever we like) on the Vue instance. The property contains the window scroll position as an [x,y]array.
这会position在 Vue 实例上创建一个响应式属性(可以随意命名)。该属性包含作为[x,y]数组的窗口滚动位置。
Feel free to play around with this CodeSandbox demo.
随意使用这个 CodeSandbox 演示。
Here's the code of the mixin. It's thoroughly commentated, so it should not be too hard to get an idea how it works:
这是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)
}
}
}
回答by Eduardo Martins
I think the best approach is just add ".passive"
我认为最好的方法是添加“.passive”
v-on:scroll.passive='handleScroll'
回答by Federico Moretti
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.
我知道这是一个老问题,但我找到了一个更好的解决方案Vue.js 2.0+ 自定义指令:我也需要绑定滚动事件,然后我实现了这个。
First of, using @vue/cli, add the custom directive to src/main.js(before the Vue.js instance) or wherever you initiate it:
首先,使用@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);
}
});
Then, add the custom v-scrolldirective to the element and/or the component you want to bind on. Of course you have to insert a dedicated method: I used handleScrollin my example.
然后,将自定义v-scroll指令添加到要绑定的元素和/或组件。当然你必须插入一个专用的方法:我handleScroll在我的例子中使用过。
<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.
在这里您不必再关心 Vue.js 生命周期,因为自定义指令本身就是如此。

