由於項目需求,最近開始轉到微信公衆號開發,接觸到了Vue框架,這個效果的實現雖然說是基於Vue框架下實現的,可是一樣也能夠借鑑到其餘地方,原理都是同樣的。css
其實js作這個效果仍是挺簡單的,由於在css中咱們能夠設置一個元素的position: fixed;
,這樣它就能夠固定在那裏,這樣無論頁面怎麼滾動,它的位置都不受影響,因此咱們的思路就是在合適的時機把要吸頂的頭部元素的position屬性設置爲fixed就能夠了。可是這個合適的時機是何時呢,這就須要咱們計算了,咱們須要監聽頁面的滾動狀態,當頁面滾動到要吸頂元素所處的位置的時候就是咱們設置它固定的時候,因此就須要咱們:ios
在mounted回調中加入如下代碼:瀏覽器
mounted() { // handleScroll爲頁面滾動的監聽回調 window.addEventListener('scroll', this.handleScroll); },
同時在destroyed回調中移除監聽:微信
destroyed(){ window.removeEventListener('scroll', this.handleScroll); },
計算出來這個距離以後就能夠肯定固定吸頂元素的時機了,若是你的吸頂元素上面的元素的高度是固定的話,那就簡單了,直接在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); });
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,這樣得出來的值纔剛恰好,若是有知道的朋友能夠幫忙解惑一下。dom
上面咱們獲得了一個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>
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>
<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>
參考優化