在優(yōu)化項(xiàng)目的時(shí)候, 產(chǎn)品提出需求需要在頁面滾動(dòng)到當(dāng)前元素下面的時(shí)候, 此元素自動(dòng)固定到頁面最頂部, 就是類似于百度的吸頂效果,如圖


話不多算,直接上干貨:
? ?你在網(wǎng)上找到的一般是這樣的實(shí)現(xiàn)代碼

但是:
這樣的代碼能實(shí)現(xiàn)需求嗎?? ?并不能, 在移動(dòng)端可以,但是在PC端不行的
我就試著寫了一個(gè)原生的demo,發(fā)現(xiàn)原生的是可以實(shí)現(xiàn)需求的,因?yàn)槲覀兪莢ue項(xiàng)目,所以這里就不重點(diǎn)體現(xiàn);
解決方案(免費(fèi))
最終通過很久的研究,實(shí)現(xiàn)了需求:
使用?obj.getBoundingClientRect().top?
定義:這個(gè)?API?可以告訴你頁面中某個(gè)元素相對瀏覽器視窗上下左右的距離。
使用:tab 吸頂可以使用?obj.getBoundingClientRect().top?代替?scrollTop - offsetTop,代碼如下:
//css
.isFixed{
? ? ? ? position: fixed;
? ? ? ? top: 60px;//自己根據(jù)需求設(shè)定
? ? ? ? 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() {//// 事件監(jiān)聽滾動(dòng)條
? ? ? this.headerFixed= false;
? ? ? window.addEventListener('scroll', this.handleScroll,true)//建議第三個(gè)參數(shù)為true,我原來沒有設(shè)置導(dǎo)致沒有深度監(jiān)聽
? ? },
? ? methods: {
? ? ? //主要處理函數(shù), 判斷目標(biāo)元素吸頂?shù)臅r(shí)機(jī)
? ? ? handleScroll () {
? ? ? ? let offsetTop = this.$refs.fixedHeaderRoot.getBoundingClientRect().top;
? ? ? ? this.headerFixed = offsetTop<0?true:false
? ? ? ? // some code
? ? ? }
? ? },
? }
實(shí)現(xiàn)方法也是通過動(dòng)態(tài)給目標(biāo)元素增加固定定位的屬性, 相信仔細(xì)研究,一眼你就能明白
但是.你以為這樣就結(jié)束了,你會(huì)發(fā)現(xiàn)

這是為什么呢,可能滾動(dòng)的太頻繁,頁面還沒有重新加載到? this.$refs;所以,我的解決辦法想當(dāng)?shù)暮唵?
//css
.isFixed{
? ? ? ? position: fixed;
? ? ? ? top: 60px;//自己根據(jù)需求設(shè)定
? ? ? ? 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() {//// 事件監(jiān)聽滾動(dòng)條
? ? ? this.headerFixed= false;
? ? ? window.addEventListener('scroll', this.handleScroll,true)//建議第三個(gè)參數(shù)為true,我原來沒有設(shè)置導(dǎo)致沒有深度監(jiān)聽
? ? },
? ? methods: {
? ? ? //主要處理函數(shù), 判斷目標(biāo)元素吸頂?shù)臅r(shí)機(jī)
? ? ? handleScroll () {
? ? ? ?
let offsetTop = this.$refs.fixedHeaderRoot.getBoundingClientRect().top;????????let offsetTop = this.$el.querySelector('#fixedHeaderRoot').getBoundingClientRect().top;
? ? ? ? this.headerFixed = offsetTop<0?true:false
? ? ? }
? ? },
? ??????destroyed() {//組件銷毀時(shí)解除監(jiān)聽
????????????window.removeEventListener("scroll", this.handleScroll);
????????},
}
在使用中發(fā)現(xiàn)如下報(bào)錯(cuò):

經(jīng)過排查發(fā)現(xiàn)是路由改變組價(jià)銷毀,但其實(shí)頁面并沒有關(guān)閉, 此時(shí)我們已經(jīng)解除了滾動(dòng)監(jiān)聽, 所以報(bào)Cannot read property 'getBoundingClientRect' of null
所以, 取消生命周期(銷毀后的解除滾動(dòng)監(jiān)聽)
//組件銷毀時(shí)解除監(jiān)聽?
destroyed() {? ? ? ? ? ?????window.removeEventListener("scroll", this.handleScroll);????????},