Как прослушать событие прокрутки окна в компоненте VueJS?
Я хочу прослушать событие прокрутки окна в моем компоненте Vue. Вот что я пробовал до сих пор:
<my-component v-on:scroll="scrollFunction">
...
</my-component>
С scrollFunction(event)
, определяемой в моих методах компонентов, но она не работает.
Кто-нибудь знает, как это сделать?
Спасибо!
Ответы
Ответ 1
На самом деле я нашел решение. Я добавляю прослушиватель событий в событие 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);
}
}
Надеюсь, это поможет!
Ответ 2
Ваши требования были к компоненту, но вы закончили с добавлением в теле, а не в компоненте. Конечно, вы можете сделать это и для определенного элемента, но эй... Вот что работает непосредственно с пользовательскими компонентами Vue.
<MyCustomComponent nativeOnScroll={this.handleScroll}>
или же
<my-component v-on:scroll.native="handleScroll">
и определить метод для handleScroll. Просто!
Ответ 3
По моему опыту, использование прослушивателя событий при прокрутке может создать много шума из-за передачи в этот поток событий, что может вызвать проблемы с производительностью, если вы выполняете громоздкую функцию handleScroll
.
Я часто использую технику, показанную здесь в ответе с самым высоким рейтингом, но я добавляю debounce поверх него, обычно о 100ms
, который дает хорошее соотношение производительности к UX.
Вот пример использования ответа с самым высоким рейтингом и добавлением отклика 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);
}
}
Попробуйте изменить значение 100
на 0
и 1000
, чтобы увидеть разницу в том, как/когда вызывается handleScroll
.
БОНУС: Вы также можете сделать это еще более кратким и многократно используемым способом с помощью библиотеки, подобной vue-scroll
. Это отличный пример использования для вас, чтобы узнать о пользовательских директивах в Vue, если вы их еще не видели. Проверьте https://github.com/wangpin34/vue-scroll.
Это также большое руководство Сары Драснер в документах Vue: https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html
Ответ 4
Я нуждался в этой функции много раз, поэтому я извлек ее в миксин. Это можно использовать так:
import windowScrollPosition from 'path/to/mixin.js'
new Vue({
mixins: [ windowScrollPosition('position') ]
})
Это создает свойство реактивной position
(может называться как угодно) в экземпляре Vue. Свойство содержит позицию прокрутки окна в виде массива [x,y]
.
Не стесняйтесь поиграть с этой демонстрацией CodeSandbox.
Здесь код миксина. Это тщательно прокомментировано, поэтому не должно быть слишком сложно понять, как это работает:
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)
}
}
}
Ответ 5
Начиная с Vue.js 2.3. 0+ есть модификатор события .passive. Так что он работает как addEventListenner.
<div v-on:scroll.passive="onScroll">...</div>
Модификаторы событий Vue.js
Ответ 6
Я думаю, что лучший подход - просто добавить ".passive"
v-on:scroll.passive='handleScroll'