前端/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秒内无论触发多少次,只执行最后一次。

Logo

前往低代码交流专区

更多推荐