Vue开发实现吸顶效果的示例代码


Posted in Javascript onAugust 21, 2018

因为项目需求,最近开始转到微信公众号开发,接触到了Vue框架,这个效果的实现虽说是基于Vue框架下实现的,但是同样也可以借鉴到其他地方,原理都是一样的。

进入正题,先看下效果图:

Vue开发实现吸顶效果的示例代码 

其实js做这个效果还是挺简单的,因为在css中我们可以设置一个元素的 position: fixed;

,这样它就可以固定在那里,这样不管页面怎么滚动,它的位置都不受影响,所以我们的思路就是在合适的时机把要吸顶的头部元素的position属性设置为fixed就可以了。但是这个合适的时机是什么时候呢,这就需要我们计算了,我们需要监听页面的滚动状态,当页面滚动到要吸顶元素所处的位置的时候就是我们设置它固定的时候,所以就需要我们:

1.监听页面的滚动状态:

在mounted回调中加入以下代码:

mounted() {
 // handleScroll为页面滚动的监听回调
 window.addEventListener('scroll', this.handleScroll);
 },

同时在destroyed回调中移除监听:

destroyed(){
 window.removeEventListener('scroll', this.handleScroll);
},

2.计算吸顶元素到页面顶部的距离:

计算出来这个距离之后就可以确定固定吸顶元素的时机了,如果你的吸顶元素上面的元素的高度是固定的话,那就简单了,直接在handleScroll方法中进行判断就可以了,可以直接跳到第三步了,如果是动态的,那就需要我们在接口请求完数据,dom元素渲染完之后进行动态计算了,Vue中有一个很好用的方法,可以很方便的监听dom渲染完成:

// 监听dom渲染完成
this.$nextTick(function(){
 // 这里fixedHeaderRoot是吸顶元素的ID
 let header = document.getElementById("fixedHeaderRoot");
 // 这里要得到top的距离和元素自身的高度
 this.offsetTop = header.offsetTop;
 this.offsetHeight = header.offsetHeight;
 console.log("offsetTop:" + this.offsetTop + "," + this.offsetHeight);
});

3.判断页面滚动距离:

handleScroll(){
 // 得到页面滚动的距离
 let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
 // 判断页面滚动的距离是否大于吸顶元素的位置
 this.headerFixed = scrollTop > (this.offsetTop - this.offsetHeight * 2);
},

ps:这里理论上其实应该是scrollTop > (this.offsetTop - this.offsetHeight),但是不知道为啥我这里做出来后滚动到吸顶元素位置的时候scrollTop还是比this.offsetTop - this.offsetHeight的值小,所以这里*2,这样得出来的值才刚刚好,如果有知道的朋友可以帮忙解惑一下。

上面我们得到了一个headerFixed的boolean属性值,接下来我们只需要根据它的值来设置吸顶元素的 position: fixed; 属性就可以了。 我们可以写一个css样式:

.isFixed{
 position: fixed;
 top: px2rem(110);
 left: px2rem(20);
 right: px2rem(20);
}

然后Vue可以在dom元素里这样动态设置class,非常方便:

<div id="fixedHeaderRoot">
 <div id="knowPointHeader" class="knowPointHeader" :class="headerFixed?'isFixed':''">
 <div><span>知识模块</span></div>
 <div><span>知识点</span></div>
 <div><span>能力要求</span></div>
 </div>
</div>

其实到这里这个效果已经实现完成了,不过我在测试过程中发现,因为ios手机页面滚动到底部的时候,还可以上拉,有一个橡皮筋效果,这个效果会导致一个我们页面的一个Bug,因为它的这种橡皮筋效果也会触发页面滚动的监听,当数据很多的时候其实看不出来,只有当数据刚好占满屏幕的时候,这个时候你再继续往上滑动屏幕,就会触发页面的滚动监听,这个时候handleScroll方法中计算出来的值scrollTop是大于吸顶元素top的距离,所以吸顶元素会被设置为固定属性,大家知道一个元素一旦被设置为 position: fixed; ,那么它就会相对于浏览器窗口进行定位,这样我们下面的内容就会往上顶,这样的话scrollTop的值又小于了吸顶元素top的距离,这样headerFixed属性又为false, position: fixed; 属性又没有了,这样它就又相对与它原本的父元素进行定位,这样就成了一个循环,你会发现页面会上下跳到,这样是肯定不行的,所以我下面又针对这个问题进行了一个优化,当然这个方案感觉不是特别完美,不过确实可以解决这个问题。

通过上面的分析我们可以得知造成这个问题的原因是因为我们把设置了元素的 position: fixed; 属性,使得下面的内容往上顶,所以要想解决这个问题,那我们就不固定这个元素,但是这样的话就达不到吸顶的效果了,所以我们需要再加一个和吸顶元素一模一样的元素,它一直就是固定状态:

<div id="fixedHeaderRootReal">
 <div class="knowPointHeader isFixed" v-show="headerFixed">
 <div><span>知识模块</span></div>
 <div><span>知识点</span></div>
 <div><span>能力要求</span></div>
 </div>
</div>

这个元素默认是隐藏的,只有当页面滚动的距离达到了它的位置的时候我们才让它显示,由于它是固定状态,所以它的隐藏显示并不会对页面产生影响,这样下面的内容就不会往上顶了,就可以解决ios手机上拉页面橡皮筋效果的Bug了,当然这种方式有些取巧,但是暂时没有更好的解决方案了,如果大家有更好的解决方案,欢迎在下面评论。最后给大家看一下我的页面布局:

<div v-show="kpointListShow" class="knowPointList">
  <div id="fixedHeaderRoot">
  <div id="knowPointHeader" class="knowPointHeader">
   <div><span>知识模块</span></div>
   <div><span>知识点</span></div>
   <div><span>能力要求</span></div>
  </div>
  </div>
  <div id="fixedHeaderRootReal">
  <div class="knowPointHeader isFixed" v-show="headerFixed">
   <div><span>知识模块</span></div>
   <div><span>知识点</span></div>
   <div><span>能力要求</span></div>
  </div>
  </div>
  <div class="knowPointItem" v-for="(kpointItem,index) in rows.kpointList" :key="index">
  <div><span>{{kpointItem.knowModule}}</span></div>
  <div><span>{{kpointItem.knowPoint}}</span></div>
  <div><span>{{kpointItem.abilityRequire}}</span></div>
  </div>
</div>

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

Javascript 相关文章推荐
js获取图片长和宽度的代码
Nov 24 Javascript
JavaScript中的对象的extensible属性介绍
Dec 30 Javascript
利用prop-types第三方库对组件的props中的变量进行类型检测
May 02 Javascript
解析Vue.js中的组件
Feb 02 Javascript
使用Vue如何写一个双向数据绑定(面试常见)
Apr 20 Javascript
详解JavaScript事件循环机制
Sep 07 Javascript
微信小程序实现多选功能
Nov 04 Javascript
vue项目中引入vue-datepicker插件的详解
May 14 Javascript
详解Vue.js和layui日期控件冲突问题解决办法
Jul 25 Javascript
React学习之JSX与react事件实例分析
Jan 06 Javascript
JavaScript实现多个物体同时运动
Mar 12 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
Jul 27 Javascript
js canvas实现红包照片效果
Aug 21 #Javascript
js实现简单选项卡功能
Mar 23 #Javascript
js实现轮播图的完整代码
Oct 26 #Javascript
JQuery扩展对象方法操作示例
Aug 21 #jQuery
详解Vue结合后台的列表增删改案例
Aug 21 #Javascript
JavaScript事件发布/订阅模式原理与用法分析
Aug 21 #Javascript
javascript和php使用ajax通信传递JSON的实例
Aug 21 #Javascript
You might like
php数组函数序列之array_pop() - 删除数组中的最后一个元素
2011/11/07 PHP
php操作JSON格式数据的实现代码
2011/12/24 PHP
ThinkPHP字符串函数及常用函数汇总
2014/07/18 PHP
php动态添加url查询参数的方法
2015/04/14 PHP
PHP单例模式简单用法示例
2017/06/23 PHP
JavaScript 事件参考手册
2008/12/24 Javascript
JQuery Ajax通过Handler访问外部XML数据的代码
2010/06/01 Javascript
javascript字符串拼接的效率问题
2010/12/25 Javascript
javascript图片相似度算法实现 js实现直方图和向量算法
2014/01/14 Javascript
js实现九宫格图片半透明渐显特效的方法
2015/02/16 Javascript
jquery+ajax请求且带返回值的代码
2015/08/12 Javascript
javascript制作照片墙及制作过程中出现的问题
2016/04/04 Javascript
微信小程序 教程之列表渲染
2016/10/18 Javascript
JS中substring与substr的用法
2016/11/16 Javascript
除Console.log()外更多的Javascript调试命令
2018/01/24 Javascript
js实现图片推拉门效果代码实例
2019/05/18 Javascript
layuiAdmin循环遍历展示商品图片列表的方法
2019/09/16 Javascript
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
vuejs element table 表格添加行,修改,单独删除行,批量删除行操作
2020/07/18 Javascript
[57:22]完美世界DOTA2联赛PWL S2 FTD vs PXG 第二场 11.27
2020/12/01 DOTA
python赋值操作方法分享
2013/03/23 Python
Python简单实现控制电脑的方法
2018/01/22 Python
Numpy中转置transpose、T和swapaxes的实例讲解
2018/04/17 Python
Python机器学习k-近邻算法(K Nearest Neighbor)实例详解
2018/06/25 Python
Django使用uwsgi部署时的配置以及django日志文件的处理方法
2019/08/30 Python
浅析Python+OpenCV使用摄像头追踪人脸面部血液变化实现脉搏评估
2019/10/17 Python
一款纯css3实现的鼠标悬停动画按钮
2014/12/29 HTML / CSS
Kathmandu美国网站:新西兰户外运动品牌
2019/03/23 全球购物
设计师大码女装:11 Honoré
2020/05/03 全球购物
初中生学习的自我评价
2013/11/14 职场文书
大学生暑期实践感言
2014/02/26 职场文书
2015年销售内勤工作总结
2015/04/27 职场文书
光荣之路观后感
2015/06/12 职场文书
创业计划书之宠物店
2019/09/19 职场文书
Nginx解决403 forbidden的完整步骤
2021/04/01 Servers
python标准库ElementTree处理xml
2022/05/20 Python