参考了几位前辈们的做法,学习过程中发现吸顶效果其实很简单,关键取决于css中的 position:fixed属性,我们的目标就是动态给元素添加一个新属性(替换或增加class),使其能固定在页面上。下面就来分享一下我的做法。
首先在mounted钩子中设置滚轮监听事件,顺便复习一下mounted和created的区别:
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
同在mounted中,计算设定元素到页面顶部的距离。这里加60的原因是因为我的导航栏高度固定为60,如果不是在嵌套页面里面的话大家按需添加。
nextTick应用场景:需要在视图更新之后,基于新的视图进行操作。大家可以参考一下这篇文章中的例子二加深理解https://segmentfault.com/a/1190000012861862
initHeight方法:获取页面滚动距离,判断滚动距离是否大于元素到页面顶部距离。
isFixed css
所以总体的执行流程就是:页面发生滚动->开始计算设定元素到页面顶部的距离->如果滚动距离大于页面元素到顶部距离,添加设定元素的class为isFixed进行固定。
到此吸顶效果就做好了,可是大家会发现isFixed中没有设置宽度,这样会导致吸顶效果发生的同时,宽度与原来的不一致,所以下面要做的就是利用onresize方法监听浏览器窗口大小,达到自适应的效果。
实现方法也非常简单,就是获取元素外层的宽度,存储在一个变量中,每次浏览器大小发生变化时,在onresize的回调函数中给变量赋值,同时js控制宽度实时更新即可
源码:
<el-col :span="6" id="colWidth">
<el-card shadow="hover" class="card" style="margin-right:15px;" id="fixedCard" :class="{'isFixed':fixed}">
<div slot="header">
<span><i class=""></i>步骤条</span>
</div>
<steps></steps>
</el-card>
</el-col>
export default {
data(){
return{
offsetTop:0,
offsetWidth:0,
colWidth:0,
fixed:false,
}
},
mounted(){
//对整个页面滚轮进行监听,每发生一次滚轮事件,执行一次方法
window.addEventListener('scroll',this.initHeight);
//对浏览器窗口大小触发事件进行监听
window.onresize = () =>{
//宽度借用,赋值
this.colWidth = document.getElementById("colWidth").offsetWidth;
this.offsetWidth = this.colWidth-15;
document.getElementById("fixedCard").style.width = this.offsetWidth+'px'
}
// DOM异步更新 对未来更新后的视图进行操作 在更新后执行
this.$nextTick(()=>{
//获取到达页面顶端的值
var height = document.getElementById("fixedCard")
this.offsetTop = height.offsetTop+60;
//获取宽度
this.offsetWidth = height.offsetWidth;
console.log(1)
})
},
destroyed(){
//移除监听
window.removeEventListener('scroll',this.initHeight);
},
methods:{
initHeight(){
//兼容性,获取页面滚动距离
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
//判断滚动距离是否大于元素到顶端距离
this.fixed = scrollTop>this.offsetTop?true:false;
//宽度赋值
document.getElementById("fixedCard").style.width = this.offsetWidth+'px'
}
}
}
</script>
<style scoped>
.card{
margin-bottom: 15px
}
span{
color: #409EFF;
font-size: 20px;
}
.isFixed{
position: fixed;
top: 0;
}
</style>