在优化项目的时候, 产品提出需求需要在页面滚动到当前元素下面的时候, 此元素自动固定到页面最顶部, 就是类似于百度的吸顶效果,如图
话不多算,直接上干货:
你在网上找到的一般是这样的实现代码
但是:
这样的代码能实现需求吗? 并不能, 在移动端可以,但是在PC端不行的
我就试着写了一个原生的demo,发现原生的是可以实现需求的,因为我们是vue项目,所以这里就不重点体现;
解决方案(免费)
最终通过很久的研究,实现了需求:
使用 obj.getBoundingClientRect().top
定义:这个 API 可以告诉你页面中某个元素相对浏览器视窗上下左右的距离。
使用:tab 吸顶可以使用 obj.getBoundingClientRect().top 代替 scrollTop - offsetTop,代码如下:
//css
.isFixed{
position: fixed;
top: 60px;//自己根据需求设定
z-index: 999;
width: 100%;
}
// html
<div class="container" ref="fixedHeaderRoot" id="fixedHeaderRoot" >
<div class="title-box" :class="headerFixed== true ? 'isFixed' :''">
// some code
</div>
</div>
// vue
export default {
data(){
return{
headerFixed: false
}
},
created() {//// 事件监听滚动条
this.headerFixed= false;
window.addEventListener('scroll', this.handleScroll,true)//建议第三个参数为true,我原来没有设置导致没有深度监听
},
methods: {
//主要处理函数, 判断目标元素吸顶的时机
handleScroll () {
let offsetTop = this.$refs.fixedHeaderRoot.getBoundingClientRect().top;
this.headerFixed = offsetTop<0?true:false
// some code
}
},
}
实现方法也是通过动态给目标元素增加固定定位的属性, 相信仔细研究,一眼你就能明白
但是.你以为这样就结束了,你会发现
这是为什么呢,可能滚动的太频繁,页面还没有重新加载到 this.$refs;所以,我的解决办法想当的简单:
//css
.isFixed{
position: fixed;
top: 60px;//自己根据需求设定
z-index: 999;
width: 100%;
}
// html
<div class="container" ref="fixedHeaderRoot" id="fixedHeaderRoot" >
<div class="title-box" :class="headerFixed== true ? 'isFixed' :''">
// some code
</div>
</div>
// vue
export default {
data(){
return{
headerFixed: false
}
},
created() {//// 事件监听滚动条
this.headerFixed= false;
window.addEventListener('scroll', this.handleScroll,true)//建议第三个参数为true,我原来没有设置导致没有深度监听
},
methods: {
//主要处理函数, 判断目标元素吸顶的时机
handleScroll () {
let offsetTop = this.$refs.fixedHeaderRoot.getBoundingClientRect().top;let offsetTop = this.$el.querySelector('#fixedHeaderRoot').getBoundingClientRect().top;
this.headerFixed = offsetTop<0?true:false
}
},
destroyed() {//组件销毁时解除监听
window.removeEventListener("scroll", this.handleScroll);
},
}
在使用中发现如下报错:
经过排查发现是路由改变组价销毁,但其实页面并没有关闭, 此时我们已经解除了滚动监听, 所以报Cannot read property 'getBoundingClientRect' of null
所以, 取消生命周期(销毁后的解除滚动监听)
//组件销毁时解除监听
destroyed() { window.removeEventListener("scroll", this.handleScroll); },