我想听听Vue组件中的窗口滚动事件。这是我到目前为止所尝试的:
SELECT CONVERT(datetime,funded,103) AS funded
FROM table
在我的组件方法中定义了<my-component v-on:scroll="scrollFunction">
...
</my-component>
,但它似乎无法正常工作。
任何人都知道如何做到这一点?
谢谢!
答案 0 :(得分:68)
其实我找到了解决方案。我在创建组件时在scrollFunction(event)
事件上添加了一个事件监听器。此外,请确保在销毁组件时删除事件侦听器。
scroll
希望这有帮助!
答案 1 :(得分:5)
我知道这是一个老问题,但是我找到了Vue.js 2.0+ Custom Directives更好的解决方案:我也需要绑定滚动事件,然后我实现了它。
首先,使用@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);
}
});
然后,将自定义v-scroll
指令添加到要绑定的元素和/或组件。当然,您必须插入一个专用方法:我在示例中使用了handleScroll
。
<my-component v-scroll="handleScroll"></my-component>
最后,将您的方法添加到组件中。
methods: {
handleScroll: function() {
// your logic here
}
}
这里不再需要关心Vue.js生命周期,因为自定义指令本身就可以。
答案 2 :(得分:4)
您的要求是在组件上,但是最后增加了主体,而不是在组件上。当然,您也可以在特定元素上执行此操作,但是,嘿...这就是直接与Vue自定义组件一起使用的功能。
<MyCustomComponent nativeOnScroll={this.handleScroll}>
或
<my-component v-on:scroll.native="handleScroll">
并为handleScroll定义一个方法。简单!
答案 3 :(得分:3)
这样的事情怎么办?顺便说一下,这是 Vue 3
setup() {
function doOnScroll(event) {
window.removeEventListener("scroll", doOnScroll);
console.log("stop listening");
// your code here ....
setTimeout(() => {
window.addEventListener("scroll", doOnScroll, { passive: true });
console.log("start listening");
}, 500);
}
window.addEventListener("scroll", doOnScroll, { passive: true });
}
这里的想法是只侦听滚动事件一次,执行您的脚本,然后在 setTimeout
函数中延迟再次重新附加滚动侦听器。如果在此延迟之后页面仍在滚动,则将再次处理滚动事件。
基本上滚动事件每 500 毫秒只监听一次(在这个例子中)。
我使用它只是为了在滚动过程中添加一个 css 类以移开按钮。
答案 4 :(得分:1)
根据我的经验,滚动到事件流中使用事件监听器会产生大量噪音,如果您正在执行庞大的handleScroll
函数,则会导致性能问题。
我经常在评分最高的答案中使用此处显示的技术,但我会在其上添加去抖动功能,通常大约100ms
会产生良好的性能与用户体验比率。
以下是使用评分最高的答案并添加了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。
这也是Sarah Drasner在Vue文档中的出色教程:https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html
答案 5 :(得分:1)
我认为最好的方法是添加“ .passive”
v-on:scroll.passive='handleScroll'
答案 6 :(得分:1)
这不会刷新您的组件,我通过使用Vux解决了问题 为vuex“页面”创建模块
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,
};
在App.vue中:
created() {
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
},
methods: {
handleScroll () {
this.$store.dispatch("page/setCurrentScrollY", window.scrollY);
}
},
在您的组件中:
computed: {
currentScrollY() {
return this.$store.getters["page/currentScrollY"];
}
},
watch: {
currentScrollY(val) {
if (val > 100) {
this.isVisibleStickyMenu = true;
} else {
this.isVisibleStickyMenu = false;
}
}
},
效果很好。
答案 7 :(得分:0)
我已经多次需要此功能,因此我将其提取到mixin中。可以这样使用:
import windowScrollPosition from 'path/to/mixin.js'
new Vue({
mixins: [ windowScrollPosition('position') ]
})
这会在Vue实例上创建一个反应性position
属性(可以命名为任意名称)。该属性包含窗口滚动位置作为[x,y]
数组。
随时可以和this CodeSandbox demo一起玩。
这是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)
}
}
}
答案 8 :(得分:-1)
document.addEventListener('scroll', function (event) {
if ((<HTMLInputElement>event.target).id === 'latest-div') { // or any other filtering condition
}
}, true /*Capture event*/);
您可以使用它来捕获事件,这里的“latest-div”是 ID 名称,因此您可以根据 ID 捕获此处的所有滚动操作,您也可以在此处执行操作。
答案 9 :(得分:-1)
结合 this.$vuetify.breakpoint.name
和按需加载,滚动事件是一个非常有用的功能。
使用触发器。例如,一个标签:
<v-tabs
v-bind:grow="!isFullScreen()"
v-bind:vertical="isFullScreen()"
>
一些类属性:
private isUserScrolling: boolean = false;
private isLoaded: boolean = false;
private startScroll: number = 3;
对触发器做出反应的函数(必要时进行调整):
private isFullScreen(): boolean {
switch (this.$vuetify.breakpoint.name) {
case "xs":
this.startScroll = 500;
return false;
case "sm":
this.startScroll = 300;
return false;
case "md":
this.startScroll = 100;
return true;
case "lg":
this.startScroll = 50;
return true;
case "xl":
this.startScroll = 3;
return true;
}
}
添加您的活动:
created() {
window.addEventListener("scroll", this.handleScroll);
}
对您的活动做出反应:
private handleScroll(event: any): void {
this.isUserScrolling = window.scrollY > this.startScroll;
if (this.isUserScrolling && !this.isLoaded) {
// load your stuff
...
this.isLoaded = true;
}
}