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:
import windowScrollPosition from 'path/to/mixin.js'
new Vue({
mixins: [ windowScrollPosition('position') ]
})
This creates a reactive position
property (can be named whatever we like) on the Vue instance. The property contains the window scroll position as an [x,y]
array.
Feel free to play around with this CodeSandbox demo.
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:
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)
}
}
}