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 相关文章推荐
JavaScript经典效果集锦
Jul 06 Javascript
javascript在myeclipse中报错的解决方法
Oct 29 Javascript
事件委托与阻止冒泡阻止其父元素事件触发
Sep 02 Javascript
推荐10个2014年最佳的jQuery视频插件
Nov 12 Javascript
不想让浏览器运行javascript脚本的方法
Nov 20 Javascript
jQuery实现iframe父窗体和子窗体的相互调用
Jun 17 Javascript
Vue.js每天必学之内部响应式原理探究
Sep 07 Javascript
JS匿名函数和匿名自执行函数概念与用法分析
Mar 16 Javascript
JS 实现缓存算法的示例(FIFO/LRU)
Mar 20 Javascript
jQuery滑动效果实现方法分析
Sep 05 jQuery
微信小程序动画(Animation)的实现及执行步骤
Oct 28 Javascript
Node.js 多线程完全指南总结
Mar 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截取字符串长度函数
2015/10/29 PHP
PHP文件及文件夹操作之创建、删除、移动、复制
2016/07/13 PHP
php常用字符串String函数实例总结【转换,替换,计算,截取,加密】
2016/12/07 PHP
基于ThinkPHP删除目录及目录文件函数
2020/10/28 PHP
jquery animate 动画效果使用说明
2009/11/04 Javascript
asp.net+jquery滚动滚动条加载数据的下拉控件
2010/06/25 Javascript
jQuery EasyUI API 中文文档 - Documentation 文档
2011/09/29 Javascript
extjs 时间范围选择自动判断的实现代码
2014/06/24 Javascript
JavaScript检测鼠标移动方向的方法
2015/05/22 Javascript
Bootstrapvalidator校验、校验清除重置的实现代码(推荐)
2016/09/28 Javascript
JavaScript数据结构之链表的实现
2017/03/19 Javascript
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
2018/08/24 Javascript
node实现生成带参数的小程序二维码并保存到本地功能示例
2018/12/05 Javascript
解决包含在label标签下的checkbox在ie8及以下版本点击事件无效果兼容的问题
2019/10/27 Javascript
jQuery实现手风琴效果(蒙版)
2020/01/11 jQuery
[00:57]辉夜杯战队访谈宣传片—VG
2015/12/25 DOTA
Python中给List添加元素的4种方法分享
2014/11/28 Python
Python遍历文件夹和读写文件的实现方法
2017/05/10 Python
python3+pyqt5+itchat微信定时发送消息的方法
2019/02/20 Python
详解Python安装tesserocr遇到的各种问题及解决办法
2019/03/07 Python
python3利用Socket实现通信的方法示例
2019/05/06 Python
python多线程高级锁condition简单用法示例
2019/11/07 Python
python去除删除数据中\u0000\u0001等unicode字符串的代码
2020/03/06 Python
python 录制系统声音的示例
2020/12/21 Python
美国和加拿大房车出售在线分类广告:RVT.com
2018/04/23 全球购物
英国最受欢迎的在线隐形眼镜商店:VisionDirect.co.uk
2018/12/06 全球购物
印度排名第一的蛋糕、鲜花和礼品送货:Winni
2019/08/02 全球购物
KELLER SPORTS荷兰:在线订购最好的运动产品
2020/10/13 全球购物
Goodee官方商店:迷你投影仪
2021/03/15 全球购物
十佳班主任事迹材料
2014/01/18 职场文书
初二生物教学反思
2014/02/03 职场文书
设备动力科岗位职责范本
2014/02/23 职场文书
高三高考决心书
2014/03/11 职场文书
导游词之山东八仙过海景区
2019/11/11 职场文书
基于Python绘制子图及子图刻度的变换等的问题
2021/05/23 Python
MySQL索引是啥?不懂就问
2021/07/21 MySQL