本文首发于政采云前端团队博客: 基于 Vue 的两层吸顶踩坑总结
近日,在作活动页的过程当中遇到两层吸顶的需求,而且要兼容 IE9 及以上的浏览器。乍一看不就是个吸顶嘛,应该不难吧,事实证实仍是踩了不少坑才出来。兼容性问题多到吐血,我太难了。废话很少说,先看一下两层吸顶的最终实现效果,以下图所示。前端
功能点:两层吸顶,由于 Tabs 区域比较长因此在滚动过程当中点击一层 Tabs 会回弹至一层吸顶刚吸顶的位置,这个功能点和锚点有些相似。二层 Tabs 经过 hover 切换,没有回弹效果。vue
本文主要经过 VueSticky
插件来实现吸顶,实现步骤描述以下:npm
npm install vue-sticky --save
import VueSticky from "vue-sticky"
directives: { 'sticky': VueSticky, },
<ELEMENT v-sticky="{ zIndex: NUMBER, stickyTop: NUMBER, disabled: [true|false]}"> <div> <!-- sticky wrapper, IMPORTANT --> CONTENT </div> </ELEMENT>
看了 VueSticky
的源码后将该插件的实现原理简要归纳以下:浏览器
首先判断该浏览器是否支持 position:sticky;
,若支持就用 position:sticky;
来实现,若不支持就用 position:fixed;
的方式实现app
因此你们不用担忧兼容性问题,由于我已经帮你们测试过了,IE9 及以上的浏览器均可以支持。post
须要注意的是,使用 v-sticky
有几个必要条件,不然会失效:性能
overflow:hidden
或者 overflow:auto
属性吸顶元素在滚动到组件底部时,在谷歌、火狐等浏览器中,两层吸顶在消失过程当中有重叠现象,具体现象以下图所示:测试
主要缘由:第一层吸顶还符合吸顶条件,第二层吸顶已经开始消失优化
解决方案:给第一层吸顶元素添加 minHeight
属性,其大小为第一层吸顶元素的高度与第二层吸顶元素的高度的和。这里有一个须要注意的点在于:一开始第一层吸顶元素的高度并不是二者之和,因此这里就须要监听滚动事件,在吸顶元素距离底部的距离为二者高度之和的位置处给第一层吸顶元素添加 minHeight
属性this
如下代码块中,sumHeight
表示两个吸顶元素的高度和,initialHeight
表示的是第一层吸顶元素的高度
const offsetTop = document.querySelector(".xxx").offsetBottom; if (offsetBottom <= sumHeight) { document.querySelector(".xxx").style.minHeight = sumHeight; } else { document.querySelector(".xxx").style.minHeight = initialHeight; }
在 IE 浏览器中,吸顶元素滚动到组件底部时不消失,具体现象以下图所示
主要缘由:在滚动过程当中吸顶元素的 position:sticky;
属性始终存在
解决方案:监听滚动事件,当滚动到组件底部时,将 v-sticky="{ stickyTop: 0, disabled: false }"
中的 disabled
的值设为 true
便可
在 IE 浏览器中,两层吸顶元素始终吸在一块儿
主要缘由:第二层吸顶元素在不须要吸顶的区域,它的 position
值也为 sticky
解决方案:监听滚动事件,在不须要吸顶的区域设置它的 position
值为 static
便可
一样 DOM 结构的吸顶元素,在 IE 浏览器中,吸顶会变形
查看 vue-sticky
的源码,发现 position:fixed;
是设置在要吸顶的元素的第一个子元素上
所以为了兼容IE须要多加一层 div
结构
<div v-sticky="{ stickyTop: 0, disabled: false }> <div> <!-- sticky wrapper, IMPORTANT --> content </div> </div>
组件的监听与移除
mounted
回调中加入如下代码mounted() { // handleScroll 为页面滚动的监听回调 window.addEventListener('scroll', this.handleScroll); },
destroy
回调中移除监听beforeDestroy() { removeEventListener("scroll", this.handleScroll); },
用监听事件监听滚动时,吸顶消失的很突兀
sticky
,若支持用 position:sticky;
实现,不然用 position:fixed;
let supportCSSSticky = document.querySelector(".xxx").style.position === "sticky"; if (!supportCSSSticky) { // 不支持的状况下监听滚动 }
图片懒加载
本文简单的介绍了 VueSticky
插件的实现原理并分享了实战过程当中出现的问题以及解决方案,但愿对你们有所帮助。若是你们也遇到过两层吸顶的问题或者你还知道更好的解决方案,欢迎在评论区留下宝贵评论。
政采云前端团队(ZooTeam),一个年轻富有激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 50 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员构成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在平常的业务对接以外,还在物料体系、工程平台、搭建平台、性能体验、云端应用、数据分析及可视化等方向进行技术探索和实战,推进并落地了一系列的内部技术产品,持续探索前端技术体系的新边界。
若是你想改变一直被事折腾,但愿开始能折腾事;若是你想改变一直被告诫须要多些想法,却无从破局;若是你想改变你有能力去作成那个结果,却不须要你;若是你想改变你想作成的事须要一个团队去支撑,但没你带人的位置;若是你想改变既定的节奏,将会是“5 年工做时间 3 年工做经验”;若是你想改变原本悟性不错,但老是有那一层窗户纸的模糊… 若是你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的本身。若是你但愿参与到随着业务腾飞的过程,亲手推进一个有着深刻的业务理解、完善的技术体系、技术创造价值、影响力外溢的前端团队的成长历程,我以为咱们该聊聊。任什么时候间,等着你写点什么,发给 ZooTeam@cai-inc.com