基於 Vue 的兩層吸頂踩坑總結

本文首發於政採雲前端團隊博客: 基於 Vue 的兩層吸頂踩坑總結

前言

近日,在作活動頁的過程當中遇到兩層吸頂的需求,而且要兼容 IE9 及以上的瀏覽器。乍一看不就是個吸頂嘛,應該不難吧,事實證實仍是踩了不少坑纔出來。兼容性問題多到吐血,我太難了。廢話很少說,先看一下兩層吸頂的最終實現效果,以下圖所示。前端

圖片.gif

功能點:兩層吸頂,由於 Tabs 區域比較長因此在滾動過程當中點擊一層 Tabs 會回彈至一層吸頂剛吸頂的位置,這個功能點和錨點有些相似。二層 Tabs 經過 hover 切換,沒有回彈效果。vue

實現方式

本文主要經過 VueSticky 插件來實現吸頂,實現步驟描述以下:npm

  • 安裝:npm install vue-sticky --save
  • 引入: import VueSticky from "vue-sticky"
  • 使用:
directives: {
    'sticky': VueSticky,
},
<ELEMENT v-sticky="{ zIndex: NUMBER, stickyTop: NUMBER, disabled: [true|false]}">
  <div> <!-- sticky wrapper, IMPORTANT -->
    CONTENT
  </div>
</ELEMENT>

看了 VueSticky 的源碼後將該插件的實現原理簡要歸納以下:瀏覽器

首先判斷該瀏覽器是否支持 position:sticky;,若支持就用 position:sticky; 來實現,若不支持就用 position:fixed; 的方式實現app

因此你們不用擔憂兼容性問題,由於我已經幫你們測試過了,IE9 及以上的瀏覽器均可以支持。post

生效條件

須要注意的是,使用 v-sticky 有幾個必要條件,不然會失效:性能

  • 父元素不能設置 overflow:hidden 或者 overflow:auto 屬性
  • 至少指定 top 、bottom 、left 、right 4 個值中的一個,不然只會處於相對定位
  • 父元素的高度不能低於 sticky 元素的高度
  • sticky 元素僅在其父元素內生效

問題彙總

◎ 吸頂「疊羅漢」

吸頂元素在滾動到組件底部時,在谷歌、火狐等瀏覽器中,兩層吸頂在消失過程當中有重疊現象,具體現象以下圖所示:測試

0FABCFA5-B3D1-49C1-90C7-DCDDD458223E.png

主要緣由:第一層吸頂還符合吸頂條件,第二層吸頂已經開始消失優化

解決方案:給第一層吸頂元素添加 minHeight 屬性,其大小爲第一層吸頂元素的高度與第二層吸頂元素的高度的和。這裏有一個須要注意的點在於:一開始第一層吸頂元素的高度並不是二者之和,因此這裏就須要監聽滾動事件,在吸頂元素距離底部的距離爲二者高度之和的位置處給第一層吸頂元素添加 minHeight 屬性this

如下代碼塊中,sumHeight 表示兩個吸頂元素的高度和,initialHeight 表示的是第一層吸頂元素的高度

const offsetTop = document.querySelector(".xxx").offsetBottom;
  if (offsetBottom <= sumHeight) {
      document.querySelector(".xxx").style.minHeight = sumHeight;
  } else {
      document.querySelector(".xxx").style.minHeight = initialHeight;
  }

◎ 吸頂「捨不得離開」

在 IE 瀏覽器中,吸頂元素滾動到組件底部時不消失,具體現象以下圖所示

702DD55C-D664-4a74-9DB1-BBC268992995.png

主要緣由:在滾動過程當中吸頂元素的 position:sticky; 屬性始終存在

解決方案:監聽滾動事件,當滾動到組件底部時,將 v-sticky="{ stickyTop: 0, disabled: false }" 中的 disabled 的值設爲 true 便可

◎ 吸頂「難捨難分」

在 IE 瀏覽器中,兩層吸頂元素始終吸在一塊兒

ECE1EF93-1887-495c-8F35-19552522A406.png

主要緣由:第二層吸頂元素在不須要吸頂的區域,它的 position 值也爲 sticky

解決方案:監聽滾動事件,在不須要吸頂的區域設置它的 position 值爲 static 便可

◎ 吸頂「變形」

一樣 DOM 結構的吸頂元素,在 IE 瀏覽器中,吸頂會變形

查看 vue-sticky 的源碼,發現 position:fixed; 是設置在要吸頂的元素的第一個子元素上

58BFFFDC-8353-4A35-87FC-C7848155842E.png

所以爲了兼容IE須要多加一層 div 結構

<div v-sticky="{ stickyTop: 0, disabled: false }>
    <div> <!-- sticky wrapper, IMPORTANT -->
        content
    </div>
</div>

注意事項

  • 組件的監聽與移除

    • mounted 回調中加入如下代碼
    mounted() {
        // handleScroll 爲頁面滾動的監聽回調
        window.addEventListener('scroll', this.handleScroll);
    },
    • 同時要在 destroy 回調中移除監聽
    beforeDestroy() {
        removeEventListener("scroll", this.handleScroll);
    },

優化點

  • 用監聽事件監聽滾動時,吸頂消失的很突兀

    • 判斷瀏覽器是否支持 sticky ,若支持用 position:sticky; 實現,不然用 position:fixed;
    let supportCSSSticky = document.querySelector(".xxx").style.position === "sticky";
    if (!supportCSSSticky) {
        // 不支持的狀況下監聽滾動
    }
  • 圖片懶加載

總結

本文簡單的介紹了 VueSticky 插件的實現原理並分享了實戰過程當中出現的問題以及解決方案,但願對你們有所幫助。若是你們也遇到過兩層吸頂的問題或者你還知道更好的解決方案,歡迎在評論區留下寶貴評論。

招賢納士

政採雲前端團隊(ZooTeam),一個年輕富有激情和創造力的前端團隊,隸屬於政採雲產品研發部,Base 在風景如畫的杭州。團隊現有 50 餘個前端小夥伴,平均年齡 27 歲,近 3 成是全棧工程師,妥妥的青年風暴團。成員構成既有來自於阿里、網易的「老」兵,也有浙大、中科大、杭電等校的應屆新人。團隊在平常的業務對接以外,還在物料體系、工程平臺、搭建平臺、性能體驗、雲端應用、數據分析及可視化等方向進行技術探索和實戰,推進並落地了一系列的內部技術產品,持續探索前端技術體系的新邊界。

若是你想改變一直被事折騰,但願開始能折騰事;若是你想改變一直被告誡須要多些想法,卻無從破局;若是你想改變你有能力去作成那個結果,卻不須要你;若是你想改變你想作成的事須要一個團隊去支撐,但沒你帶人的位置;若是你想改變既定的節奏,將會是「5 年工做時間 3 年工做經驗」;若是你想改變原本悟性不錯,但老是有那一層窗戶紙的模糊… 若是你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的本身。若是你但願參與到隨着業務騰飛的過程,親手推進一個有着深刻的業務理解、完善的技術體系、技術創造價值、影響力外溢的前端團隊的成長曆程,我以爲咱們該聊聊。任什麼時候間,等着你寫點什麼,發給 ZooTeam@cai-inc.com

相關文章
相關標籤/搜索