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


Posted in Javascript onJanuary 17, 2018

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

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

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

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

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

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

:scrollTop(滚动之根本)

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

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

一、组件html结构:

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

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

注意看注释::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)
  },

这里写的有点??铝耍?柚?etTimeout延迟是为了能够获取到元素(谁有好办法快推荐给我),为了在滚动中能够对应列表显示锚点当前状态,存了一个数据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。但是一时也没有更好的办法来实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
原生js的弹出层且其内的窗口居中
May 14 Javascript
javascript实现2016新年版日历
Jan 25 Javascript
JS 面向对象之继承---多种组合继承详解
Jul 10 Javascript
移动端基础事件总结与应用
Jan 12 Javascript
Vue项目中引入外部文件的方法(css、js、less)
Jul 24 Javascript
react-native 完整实现登录功能的示例代码
Sep 11 Javascript
深入理解Node.js中通用基础设计模式
Sep 19 Javascript
微信小程序授权获取用户详细信息openid的实例详解
Sep 20 Javascript
JS判断数组那点事
Oct 10 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
Jul 10 Javascript
jQuery实现form表单基于ajax无刷新提交方法实例代码
Nov 04 jQuery
vue3获取当前路由地址
Feb 18 Vue.js
详解微信小程序审核不通过的解决方法
Jan 17 #Javascript
swiper动态改变滑动内容的实现方法
Jan 17 #Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
Jan 17 #Javascript
使用Vue开发一个实时性时间转换指令
Jan 17 #Javascript
angularjs 页面自适应高度的方法
Jan 17 #Javascript
VueJs监听window.resize方法示例
Jan 17 #Javascript
详解AngularJS之$window窗口对象
Jan 17 #Javascript
You might like
PHP4中session登录页面的应用
2008/07/25 PHP
中英文字符串翻转函数
2008/12/09 PHP
PHP同时连接多个mysql数据库示例代码
2014/03/17 PHP
PHP-FPM之Chroot执行环境详解
2015/08/03 PHP
php实现图片以base64显示的方法
2016/10/13 PHP
Yii2选项卡的简单使用
2017/05/26 PHP
响应鼠标变换表格背景或者颜色的代码
2009/03/30 Javascript
在Iframe中获取父窗口中表单的值(示例代码)
2013/11/22 Javascript
javascript中replace( )方法的使用
2015/04/24 Javascript
JQuery给网页更换皮肤的方法
2015/05/30 Javascript
Java中Timer的用法详解
2015/10/21 Javascript
jquery选择器中的空格与大于号&gt;、加号+与波浪号~的区别介绍
2016/06/24 Javascript
JS表格组件BootstrapTable行内编辑解决方案x-editable
2016/09/01 Javascript
JavaScript DOM节点操作实例小结(新建,删除HTML元素)
2017/01/19 Javascript
基于 Vue 实现一个酷炫的 menu插件
2017/11/14 Javascript
Angular模版驱动表单的使用总结
2018/05/05 Javascript
Bootstrap 实现表格样式、表单布局的实例代码
2018/12/09 Javascript
vue-cli2 构建速度优化的实现方法
2019/01/08 Javascript
js中int和string数据类型互相转化实例
2019/01/16 Javascript
js实现删除li标签一行内容
2019/04/16 Javascript
Vue自定义全局Toast和Loading的实例详解
2019/04/18 Javascript
Python编程pygal绘图实例之XY线
2017/12/09 Python
Django读取Mysql数据并显示在前端的实例
2018/05/27 Python
python计算两个数的百分比方法
2018/06/29 Python
python将txt等文件中的数据读为numpy数组的方法
2018/12/22 Python
opencv python统计及绘制直方图的方法
2019/01/21 Python
python 直接赋值和copy的区别详解
2019/08/07 Python
Flask框架学习笔记之使用Flask实现表单开发详解
2019/08/12 Python
python3光学字符识别模块tesserocr与pytesseract的使用详解
2020/02/26 Python
HTML5中drawImage用法分析
2014/12/01 HTML / CSS
使用纯HTML5编写一款网页上的时钟的代码分享
2015/11/16 HTML / CSS
HTML5 视频播放(video),JavaScript控制视频的实例代码
2018/10/08 HTML / CSS
产品工艺师的岗位职责
2013/11/15 职场文书
2014年大学生四年规划书范文
2014/04/03 职场文书
团结友爱主题班会
2015/08/13 职场文书
Python下opencv使用hough变换检测直线与圆
2021/06/18 Python