Vue開發——實現吸頂效果

来源:https://www.cnblogs.com/xbincoder/archive/2019/08/02/11289120.html
-Advertisement-
Play Games

因為項目需求,最近開始轉到微信公眾號開發,接觸到了Vue框架,這個效果的實現雖說是基於Vue框架下實現的,但是同樣也可以借鑒到其他地方,原理都是一樣的。 進入正題,先看下效果圖: 其實js做這個效果還是挺簡單的,因為在css中我們可以設置一個元素的position: fixed;,這樣它就可以固定在 ...


因為項目需求,最近開始轉到微信公眾號開發,接觸到了Vue框架,這個效果的實現雖說是基於Vue框架下實現的,但是同樣也可以借鑒到其他地方,原理都是一樣的。

進入正題,先看下效果圖:

 

其實js做這個效果還是挺簡單的,因為在css中我們可以設置一個元素的position: fixed;,這樣它就可以固定在那裡,這樣不管頁面怎麼滾動,它的位置都不受影響,所以我們的思路就是在合適的時機把要吸頂的頭部元素的position屬性設置為fixed就可以了。但是這個合適的時機是什麼時候呢,這就需要我們計算了,我們需要監聽頁面的滾動狀態,當頁面滾動到要吸頂元素所處的位置的時候就是我們設置它固定的時候,所以就需要我們:

 

1.監聽頁面的滾動狀態:

在mounted回調中加入以下代碼:

mounted() {
  // handleScroll為頁面滾動的監聽回調
  window.addEventListener('scroll', this.handleScroll);
 },

同時在destroyed回調中移除監聽:

destroyed(){
  window.removeEventListener('scroll', this.handleScroll);
},

2.計算吸頂元素到頁面頂部的距離:

計算出來這個距離之後就可以確定固定吸頂元素的時機了,如果你的吸頂元素上面的元素的高度是固定的話,那就簡單了,直接在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);
});

3.判斷頁面滾動距離:

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,這樣得出來的值才剛剛好,如果有知道的朋友可以幫忙解惑一下。

上面我們得到了一個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>

其實到這裡這個效果已經實現完成了,不過我在測試過程中發現,因為ios手機頁面滾動到底部的時候,還可以上拉,有一個橡皮筋效果,這個效果會導致一個我們頁面的一個Bug,因為它的這種橡皮筋效果也會觸發頁面滾動的監聽,當數據很多的時候其實看不出來,只有當數據剛好占滿屏幕的時候,這個時候你再繼續往上滑動屏幕,就會觸發頁面的滾動監聽,這個時候handleScroll方法中計算出來的值scrollTop是大於吸頂元素top的距離,所以吸頂元素會被設置為固定屬性,大家知道一個元素一旦被設置為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>

這個元素預設是隱藏的,只有當頁面滾動的距離達到了它的位置的時候我們才讓它顯示,由於它是固定狀態,所以它的隱藏顯示並不會對頁面產生影響,這樣下麵的內容就不會往上頂了,就可以解決ios手機上拉頁面橡皮筋效果的Bug了,當然這種方式有些取巧,但是暫時沒有更好的解決方案了,如果大家有更好的解決方案,歡迎在下麵評論。最後給大家看一下我的頁面佈局:

<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>

參考

喜歡的麻煩動動小手點個贊來支持我,有不對的地方歡迎大家指正,有什麼問題也可以在下方留言,我看到後會第一時間回覆!謝謝您來看這篇文章!

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄 為什麼要討論this this是什麼 如何改變this的指向 為什麼要討論this this是什麼 如何改變this的指向 為什麼要討論this 代碼一: 會列印出什麼呢?是 ' I am aa ' 嗎, 結果是: 原因: 此時 this 指向 window 對象, this.aa 等同於 w ...
  • 居中是我們使用css來佈局時常遇到的情況。使用css來進行居中時,有時一個屬性就能搞定,有時則需要一定的技巧才能相容到所有瀏覽器,本文就居中的一些常用方法做個簡單的介紹。 註:本文所講方法除了特別說明外,都是相容IE6+、谷歌、火狐等主流瀏覽器的。 先來說幾種簡單的、人畜無害的居中方法: 1. 把m ...
  • 前置閱讀:簡述JavaScript模塊化(一) 在前面一文中,我們對前端模塊化所經歷的三個階段進行了瞭解: CommonJs,由於是同步的,所以主要應用於伺服器端,以Node.js為代表。 AMD,非同步模塊定義,預載入,推薦依賴前置。以require.js為代表。 CMD,通用模塊載入,懶載入,推薦 ...
  • 與數學中的集合概念類似,集合由一組無序的元素組成,且集合中的每個元素都是唯一存在的。可以回顧一下中學數學中集合的概念,我們這裡所要定義的集合也具有空集(即集合的內容為空)、交集、並集、差集、子集的特性。 在ES6中,原生的Set類已經實現了集合的全部特性,稍後我們會介紹它的用法。 我們使用JavaS ...
  • 一、HTML代碼如下: 二、JavaScript代碼如下: ...
  • 輪播效果: HTML: JS: ...
  • 在早期編寫JavaScript時,我們只需在<script>標簽內寫入JavaScript的代碼就可以滿足我們對頁面交互的需要了。但隨著時間的推移,時代的發展,原本的那種簡單粗暴的編寫方式所帶來的諸如邏輯混亂,頁面複雜,可維護性差,全局變數暴露等問題接踵而至,前輩們為瞭解決這些問題提出了很種的解決方 ...
  • 一、redux-saga解決非同步 redux-thunk 和 redux-saga 使用redux它們是必選的,二選一,它們兩個都可以很好的實現一些複雜情況下redux,本質都是為瞭解決非同步action而生,使redux保持完整性,不至於太過混亂。redux-saga 是一個用於管理Redux 應用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...