视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
基于vue监听滚动事件实现锚点链接平滑滚动的方法
2020-11-27 22:21:22 责编:小OO
文档

基于vue监听滚动事件,实现锚点链接平滑滚动

近日在做一个vue项目的餐饮模块,小编需要实现一个菜单列表显示的功能(如图所示:左边为菜单类别,右边显示相对应的菜品)

小编将此分为三个功能模块来实现(本来一张动画就清晰明了,小编太笨,只得口述一下):

1.左边点击类别,右边显示相应类别的菜品列表(平滑滚动)
2.滚动右边的滚动条,左边对应的显示当前样式
3.若从别的页面点击菜品进来该页面,则该菜品为指定效果

小编也是vue的初学者,在阅读了大量的文章后,其中借鉴//www.gxlcms.com/article/110325.htm 该文章,收到了很多启发后,结合我们的功能加以完善。小编的和借鉴的文章侧重点不同,建议大家在看之前可以先看一下上面的,以便于梳理的更清楚。

:scrollTop(滚动之根本)

在初写项目的尝试过程中,小编一直改变的是document.body.scrollTop的值来实现滚动,但是后来逐渐发现很邪门,有时给其赋值并没有作用,而且过程也很麻烦,又查阅了一些资料也没有解决办法,所以不得已放弃。

之后无意中看到:scrollTop, 便尝试开始使用vue中的属性直接进行绑定滚动的变量值,功能实现反而简单了。下面详细讲述:

一、组件html结构:

结构布局很简单,在此多说是想给大家讲述清楚一点儿右边菜品的结构,方便绑定:scrollTop属性,小编就踩了这个坑...

注意看注释::scrollTop 的位置改变菜品列表的scrollTop值,来实现相应的滚动

二、实现锚链接平滑滚动

该功能是参考之前博主的文章的,方法基本没改什么,简单易懂,直接放代码

jump(index){
 const cateItem = document.querySelectorAll('.cate-item');
 let total = cateItem[index].offsetTop;
 let distance = this.container.scrollTop // 获取到顶部的距离(this.container便是.cate-list,为了方便存起来了)
 let step = total / 50;
 this.isActive = index; // 菜单列表显示当前样式
 const _this = this;
 if (total > distance) {
 smoothDown()
 } else {
 let newTotal = distance - total
 step = newTotal / 50
 smoothUp()
 }
 function smoothDown () {
 if (distance < total) {
 distance += step
 _this.scrollTop = distance;
 setTimeout(smoothDown, 10);
 } else {
 _this.scrollTop = total
 }
 }
 function smoothUp () {
 if (distance > total) {
 distance -= step
 _this.scrollTop = distance
 setTimeout(smoothUp, 10)
 } else {
 _this.scrollTop = total
 }
 } 
 }

三、监听滚动事件,修改锚点状态

在vue中钩子函数监听菜品列表(this.container)的滚动事件,

 mounted(){
 // 监听scroll事件
 const _this = this;
 setTimeout(function(){
 _this.currentStick(); 
 const rightItem = document.querySelectorAll('.cate-item');
 const catelist = document.querySelectorAll('.cate-list')[0];
 var length = rightItem.length;
 var height = rightItem[length-1].offsetHeight;
 var scrollHeight = document.querySelectorAll('.cate-menu-wrapper')[0].offsetHeight;
 // 设置最后一个类别菜品列表的高度(小于适配器高度的话与适配器等高),不然点击锚点不能够置顶
 if(height < scrollHeight){
 rightItem[length-1].style.height = scrollHeight+'px';
 } 
 var arr =[];
 rightItem.forEach(function(v, i){
 arr.push({top: v.offsetTop, height: v.offsetHeight, index: i});
 })
 _this.itemVal = arr; 
 const cateList = document.querySelectorAll('.cate-list')[0];
 cateList.addEventListener('scroll', _this.onScroll);
 _this.container = cateList;
 }, 500)
 },

这里写的有点啰嗦了,设置setTimeout延迟是为了能够获取到元素(谁有好办法快推荐给我),为了在滚动中能够对应列表显示锚点当前状态,存了一个数据itemAll,存了该菜品类别区域的scrollTop,索引,高度。(啰嗦,太啰嗦了)

methods: {
 onScroll () {
 var _this = this;
 _this.itemVal.forEach(function(obj, i){
 _this.scrollTop = _this.container.scrollTop;
 if(_this.scrollTop >= obj.top && _this.scrollTop < (obj.top + obj.height-10)){
 // scrollTop的移动位置要在类别的菜品列表中才显示对应锚点的当前状态
 _this.isActive = obj.index;
 }
 })
 },
}

三、点击菜品进入页面,该菜品置顶的联动效果(该功能其实有隐藏性的bug,我们项目已取消该功能)

currentStick(){
 const {dishId} = this.$route.query;
 const cateContent = document.querySelectorAll('.cate-content');
 const _this = this;
 cateContent.forEach(function(v, i){
 if(v.id == dishId){
 _this.scrollTop = v.offsetTop; 
 }
 })
 },

该功能用:scrollTop绑定的话便简单了许多,之前用document.body.scrollTop 设置值一直没有作用。

好了,基本上所有的代码都帖出来了,说的应该也详细吧(我尽力了),该方法感觉其实还是在操作dom元素和js,枉用vue。但是一时也没有更好的办法来实现。

下载本文
显示全文
专题