【前端/Vue】 监听滚动事件 实现 吸附指定位置卡点的简单应用
实现过程
主要目的是滚动吸附的简单实现,过程中对于不同方法的兼容性不作介绍,与此同时,重点不在获取滚动信息,重点在怎么使滚动更合理吸附效果更丝滑。
提示:方法可能对整个网站所有页面起效,我后面发现的,具体情况是stopmove方法导致其他页面都不能滚动而其本页面还是能滚动的,所以有可能打开其他页面时得默认执行一次允许滚动的方法,具体是类似stopmove内的passive改成true。
演示环境
Vuecli/Vue2.x
Edge
常见的与滚动相关方法
具体可以去搜:
1.在vue里通过ref来获取dom,并且通过点击来控制滚动条滚动距离
2.window.addEventListener(“scroll”, func) 监听滚动
3.window.οnscrοll= func 也许与第二种有用法区别或者兼容问题
4.写在vue页面标签中的@mousewheel 写法
5.这是定位到某位置的代码,监听后通过以下代码滑动到指定位置,behavior选择滑动还是直接闪到位置,block也有必要加上,否则偶尔会因为你指定不清楚,自己都不知道是以div的顶端还是底部还是中间为目标位置,简单的说就是盒子位置自己把握,可以css设置宽高大一点测一测。
document.getElementById('xxx').scrollIntoView({ behavior: 'smooth', block: 'center'});
以上有一些看不懂的没关系,我也是小白,直接复制一搜就出来了
失败的效果
//盒子长宽满屏,滚动鼠标滑到下一个盒子中心
<template>
<div>
<div id="Position0"><div>
<div id="Position1"><div>
</div>
</template>
<script>
data(){
return{
}
},
methods:{
scrolling() {
// 滚动条距文档顶部的距离
let scrollTop = window.pageYOffset || document.documentElement.scrollTop ||
document.body.scrollTop
// 滚动条滚动的距离
let scrollStep = scrollTop - this.oldScrollTop;
console.log(scrollTop)
// 更新——滚动前,滚动条距文档顶部的距离
this.oldScrollTop = scrollTop;
//拿着方向值去判断
if (scrollStep < 0) {
console.log("滚动条向上滚动了!")
document .getElementById('Position0') .scrollIntoView({ behavior: 'smooth' })
} else {
console.log("滚动条向下滚动了!")
document .getElementById('Position1') .scrollIntoView({ behavior: 'smooth' })
}
},
},
mounted () {
// 监听页面滚动事件
var timeout;
var that = this;
window.onscroll=function(e){
console.log(e);
clearTimeout(timeout);
timeout = setTimeout(that.scrolling, 30);
}
}
</script>
效果:既然是监听滚动再定位,所以 第一下滚动是普通的滚动,然后才监听到滚动操作后,延迟了几十到几百毫秒,再给你滑到盒子附近但是位置不确定,一般到底。
成功的效果
//盒子长宽满屏,滚动鼠标滑到下一个盒子中心
<template>
<div @mousewheel="scrollInit">
<div id="Position0"><div>
<div id="Position1"><div>
</div>
</template>
<script>
data(){
return{
}
},
methods:{
scrollInit(e) {
//这个阻止滚动方法,我很早的想法,方法没毛病。
//但是过程中一直得不到合适的运用,一用就是不能滑动。
//但是加在这位置就可以保证卡点滑动的过程中页面可滚动
//加在下面的判断区域内则先滑动一小段,没到卡点页面就没法滑动了。大家可以试下
this.stopMove();
//打印值为150/-150,对应滚动上和下
console.log(e.wheelDelta);
if(e.wheelDelta<0){
console.log('down')
document.getElementById('Position1').scrollIntoView({ behavior: 'smooth', block: 'center'});
}else{
console.log('up')
document.getElementById('Position0').scrollIntoView({ behavior: 'smooth', block: 'center'});
}
},
//可以阻止滚动
stopMove(){
let m = function(e){e.preventDefault();};
document.body.style.overflow='hidden';
document.addEventListener("touchmove",m,{ passive:false });//禁止页面滑动
},
},
mounted () {
//你可能疑问,div中有@mousewheel可以触发,为什么还要初始执行一次?
//这里初始执行一次的原因,需要看方法里面的内容去理解。当然实际操作也能看到效果
this.scrollInit();
}
</script>
这里出来的效果,可以打开链接: 上海博物馆的网站首页.
过程中的发现
1.通过@mousewheel实现滚动触发、滚动监听,它已经帮你解决了鼠标滚动一下触发两次甚至多次的问题,而其他方法基本需要setTimeout来延迟几十毫秒,是每一次滚动都延迟,效果不尽人意。
2.最后就是神来之笔,在方法体开头阻止滚动,我也不知道什么原因,谁可以告诉我。没加之前,方法照样执行,但是滑动定位的代码没效果。当然一定要加在开头,如果加在判断里,初始执行一次就没意义了。stopMove方法除了让效果成功了,还解决了进入网页第一次滚动没效果的问题,所以注释里有说过,方法没毛病,只是用不出效果,而且也不是复杂的东西。
所以,我认为@mousewheel可以在执行完之后默认解除了阻止滚动。
--------------------------------------------------------2022.11.27补充--------------------------------------------------------
这个效果是我9月份边做边学完成的。
现在才了解到,虽然这个简单应用没毛病,也可以用,稍微改改判断内的操作可以设置更多的卡点,但是方法稍微有点白开水,刚接触的可能会用暂停滚动完成后再允许滚动的思想解决,并且这个方法容易对其他页面的滚动产生影响,那么后面就需要自己设置一些路由守卫啊~~公共组件啊 ~拦截器监听器巴拉巴拉,或者路由文件直接给其他页面设置跳转自动置顶,或者keep-alive等等
所以最终应该是可以用 防抖 来完成这个效果的,什么是防抖自己去查,封装一下防抖,把函数扔进去返回一个防抖版函数。。n秒内无论触发多少次,只执行最后一次。
更多推荐
所有评论(0)