最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端如何解決滾動(dòng)穿透問題詳解

 更新時(shí)間:2025年03月11日 10:46:53   作者:IT楓斗者  
這篇文章主要介紹了前端解決滾動(dòng)穿透問題的五種常見方法,并詳細(xì)分析了它們的優(yōu)缺點(diǎn)和適用場(chǎng)景,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

滾動(dòng)穿透是指在移動(dòng)端(或具有滾動(dòng)條的容器中),當(dāng)一個(gè)可滾動(dòng)的模態(tài)框(或類似元素)被打開時(shí),如果用戶在該模態(tài)框內(nèi)滾動(dòng)到盡頭,會(huì)導(dǎo)致底層頁面(或父容器)也跟著滾動(dòng)。這是一種糟糕的用戶體驗(yàn)。

以下是前端解決滾動(dòng)穿透問題的幾種常見方法,以及它們的優(yōu)缺點(diǎn)和適用場(chǎng)景:

1. overflow: hidden; (最簡(jiǎn)單,但有局限性)

  • 原理: 當(dāng)模態(tài)框打開時(shí),給 body 或根元素添加 overflow: hidden; 樣式,阻止其滾動(dòng)。模態(tài)框關(guān)閉時(shí),移除該樣式。

  • 實(shí)現(xiàn) (以 Vue 為例):

    <template>
      <div>
        <button @click="showModal = true">Open Modal</button>
        <div v-if="showModal" class="modal">
          <div class="modal-content">
            <!-- 模態(tài)框內(nèi)容 -->
            <button @click="showModal = false">Close</button>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          showModal: false,
        };
      },
      watch: {
        showModal(newValue) {
          if (newValue) {
            document.body.style.overflow = 'hidden';
          } else {
            document.body.style.overflow = ''; // 或 'auto'
          }
        },
      },
      beforeDestroy() { // 重要: 組件銷毀時(shí)也要移除
        document.body.style.overflow = '';
      }
    };
    </script>
    
    <style>
    .modal {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      overflow-y: auto; /* 允許模態(tài)框自身滾動(dòng) */
    }
    .modal-content{
       /* 模態(tài)框內(nèi)容樣式 */
    }
    </style>
    
  • 優(yōu)點(diǎn): 簡(jiǎn)單易用,代碼量少。

  • 缺點(diǎn):

    • 頁面跳動(dòng): 當(dāng) body 的滾動(dòng)條被隱藏時(shí),頁面可能會(huì)因?yàn)闈L動(dòng)條消失而產(chǎn)生輕微的跳動(dòng)(尤其是在 Windows 上)。
    • 丟失滾動(dòng)位置: 關(guān)閉模態(tài)框后,body 的滾動(dòng)位置會(huì)丟失,回到頂部。
    • 影響其他 fixed 元素: 如果頁面上有其他 position: fixed 的元素(例如固定頭部、固定側(cè)邊欄),它們的位置可能會(huì)受到影響,因?yàn)?nbsp;fixed 定位是相對(duì)于視口的,而 body 的 overflow: hidden 可能會(huì)改變視口的計(jì)算方式。
    • 鍵盤可訪問性問題: 如果模態(tài)框是使用鍵盤導(dǎo)航打開的,隱藏body的滾動(dòng)可能會(huì)導(dǎo)致焦點(diǎn)丟失或行為異常.
  • 適用場(chǎng)景: 簡(jiǎn)單的模態(tài)框,不需要保留底層頁面滾動(dòng)位置,且頁面上沒有其他復(fù)雜的 fixed 元素。

2. 阻止事件冒泡 (適用于特定場(chǎng)景)

  • 原理: 在模態(tài)框的滾動(dòng)容器上阻止 touchmove 事件的冒泡(以及可能的 wheel 事件)。

  • 實(shí)現(xiàn):

    <template>
      <div v-if="showModal" class="modal">
        <div class="modal-content" @touchmove.prevent.stop @wheel.prevent.stop>
          </div>
      </div>
    </template>
    

    或使用原生JS

    javascript 代碼解讀復(fù)制代碼 modalContent.addEventListener('touchmove', function(event) {
        event.preventDefault();
        event.stopPropagation(); //有時(shí)候不需要.stop,只阻止默認(rèn)行為
     }, { passive: false }); //passive:false 是關(guān)鍵
    
* **注意**: 必須要加上 `{ passive: false }` , 默認(rèn) passive 是 true,表示不會(huì)調(diào)用 preventDefault(). 如果你設(shè)置了 passive: true, 又調(diào)用了 preventDefault(), 瀏覽器會(huì)忽略 preventDefault(), 并報(bào)一個(gè)警告。
  • 優(yōu)點(diǎn): 只阻止模態(tài)框內(nèi)的滾動(dòng)事件,不影響其他元素。
  • 缺點(diǎn):
    • 只能阻止 touchmove 和 wheel: 無法阻止通過鍵盤(如 Page Up/Down)或滾動(dòng)條拖動(dòng)引起的滾動(dòng)。
    • 模態(tài)框內(nèi)部滾動(dòng)問題: 如果模態(tài)框內(nèi)部本身有多個(gè)可滾動(dòng)區(qū)域,阻止 touchmove 會(huì)導(dǎo)致這些區(qū)域也無法滾動(dòng)。 需要更精細(xì)的控制,例如判斷當(dāng)前滾動(dòng)元素是否已經(jīng)到達(dá)邊界。
  • 適用場(chǎng)景: 模態(tài)框內(nèi)部只有一個(gè)滾動(dòng)區(qū)域,并且不需要鍵盤或滾動(dòng)條進(jìn)行滾動(dòng)的情況。

3. position: fixed; (較好的解決方案)

  • 原理: 當(dāng)模態(tài)框打開時(shí),將 body 設(shè)置為 position: fixed;,并記錄當(dāng)前的滾動(dòng)位置(scrollTop)。關(guān)閉模態(tài)框時(shí),恢復(fù) body 的定位,并設(shè)置回之前記錄的滾動(dòng)位置。

  • 實(shí)現(xiàn):

    <template>
      <div v-if="showModal" class="modal" @touchmove.prevent>  </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          showModal: false,
          scrollTop: 0,
        };
      },
      watch: {
        showModal(newValue) {
          if (newValue) {
            this.scrollTop = window.pageYOffset || document.documentElement.scrollTop;
            document.body.style.position = 'fixed';
            document.body.style.top = `-${this.scrollTop}px`;
            document.body.style.width = '100%'; // 確保 body 寬度占滿
          } else {
            document.body.style.position = '';
            document.body.style.top = '';
            document.body.style.width = '';
            window.scrollTo(0, this.scrollTop);
          }
        },
      },
       beforeDestroy() { // 重要: 組件銷毀時(shí)也要移除
         document.body.style.position = '';
            document.body.style.top = '';
            document.body.style.width = '';
            window.scrollTo(0, this.scrollTop);
       }
    };
    </script>
    
  • 優(yōu)點(diǎn):

    • 保留滾動(dòng)位置: 關(guān)閉模態(tài)框后,body 的滾動(dòng)位置可以恢復(fù)。
    • 避免頁面跳動(dòng): position: fixed; 不會(huì)隱藏滾動(dòng)條,避免了跳動(dòng)問題。
    • 相對(duì)較好地兼容 fixed 元素: 雖然fixed會(huì)脫離文檔流,但是因?yàn)樵O(shè)置了top屬性為負(fù)的滾動(dòng)高度,整體頁面視覺上不會(huì)移動(dòng).
  • 缺點(diǎn):

    • 代碼略復(fù)雜: 需要記錄和恢復(fù)滾動(dòng)位置。
    • 兼容性問題: 在一些舊版本的 iOS Safari 中,position: fixed; 可能會(huì)導(dǎo)致一些布局問題(雖然現(xiàn)代瀏覽器基本已修復(fù))。
    • 需要處理滾動(dòng)條: 需要處理可能存在的滾動(dòng)條,例如設(shè)置bodywidth:100%, 以防止出現(xiàn)水平滾動(dòng)條。
  • 適用場(chǎng)景: 大多數(shù)情況下的模態(tài)框,需要保留底層頁面滾動(dòng)位置,且對(duì)兼容性要求不高。

4. 使用第三方庫

  • 原理: 一些第三方庫(如 body-scroll-lock)封裝了更完善的滾動(dòng)鎖定邏輯,處理了各種邊界情況和兼容性問題。

  • 實(shí)現(xiàn) (以 body-scroll-lock 為例):

    npm install body-scroll-lock
    
    <template>
      <div v-if="showModal" ref="modal" class="modal">
        <div class="modal-content">
           </div>
      </div>
    </template>
    
    <script>
    import { disableBodyScroll, enableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
    
    export default {
      data() {
        return {
          showModal: false,
        };
      },
      watch: {
        showModal(newValue) {
          if (newValue) {
            disableBodyScroll(this.$refs.modal);
          } else {
            enableBodyScroll(this.$refs.modal);
          }
        },
      },
      beforeDestroy() {
        clearAllBodyScrollLocks(); // 清除所有鎖定
      },
    };
    </script>
    
  • 優(yōu)點(diǎn):

    • 完善的解決方案: 處理了各種細(xì)節(jié)和兼容性問題。
    • 易于使用: API 簡(jiǎn)單明了。
  • 缺點(diǎn): 需要引入額外的庫,增加項(xiàng)目體積。

  • 適用場(chǎng)景: 對(duì)滾動(dòng)鎖定有較高要求,需要處理各種復(fù)雜情況,且不介意引入第三方庫的項(xiàng)目。

5. 使用overscroll-behavior (CSS 屬性,較新)

***原理**: `overscroll-behavior` CSS 屬性控制當(dāng)滾動(dòng)到達(dá)元素邊界時(shí)發(fā)生的情況。  它可以防止?jié)L動(dòng)鏈(即滾動(dòng)穿透)。
* **實(shí)現(xiàn)**:
    ```css
    .modal-content {
       overscroll-behavior: contain; /* 或 overscroll-behavior-y: contain; */
       /* 其他樣式 */
    }
    ```

* **優(yōu)點(diǎn)**:
    * **原生 CSS 解決方案**: 無需 JavaScript。
    * **性能好**: 瀏覽器原生支持,性能通常優(yōu)于 JavaScript 解決方案。
* **缺點(diǎn)**:
    * **兼容性**: 比較新的屬性,一些舊瀏覽器可能不支持(需要檢查 Can I Use:[https://caniuse.com/?search=overscroll-behavior](https://caniuse.com/?search=overscroll-behavior))。 可以考慮回退方案。
* **適用場(chǎng)景**:  如果項(xiàng)目對(duì)瀏覽器兼容性要求不高,`overscroll-behavior` 是一個(gè)非常優(yōu)雅的解決方案。

總結(jié)和選擇建議:

  • 簡(jiǎn)單場(chǎng)景,不需保留滾動(dòng)位置: overflow: hidden;
  • 模態(tài)框內(nèi)只有一個(gè)滾動(dòng)區(qū)域,且不需要鍵盤/滾動(dòng)條滾動(dòng): 阻止事件冒泡
  • 大多數(shù)情況,需要保留滾動(dòng)位置: position: fixed;
  • 需要處理復(fù)雜情況,不介意引入庫: body-scroll-lock
  • 瀏覽器兼容性允許: overscroll-behavior (首選,最優(yōu)雅)

最佳實(shí)踐是根據(jù)項(xiàng)目的具體需求和目標(biāo)瀏覽器來選擇最合適的方法。通常,position: fixed; 或 body-scroll-lock 是比較穩(wěn)妥的選擇。如果對(duì)兼容性要求不高,強(qiáng)烈推薦 overscroll-behavior。 記得在開發(fā)過程中進(jìn)行充分的測(cè)試,確保在各種設(shè)備和瀏覽器上都能正常工作。

總結(jié)

到此這篇關(guān)于前端如何解決滾動(dòng)穿透問題的文章就介紹到這了,更多相關(guān)前端滾動(dòng)穿透問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS仿Base.js實(shí)現(xiàn)的繼承示例

    JS仿Base.js實(shí)現(xiàn)的繼承示例

    這篇文章主要介紹了JS仿Base.js實(shí)現(xiàn)的繼承,結(jié)合具體實(shí)例形式分析了javascript擴(kuò)展操作及面向?qū)ο蟪绦蛟O(shè)計(jì)相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-04-04
  • 整理一下常見的IE錯(cuò)誤

    整理一下常見的IE錯(cuò)誤

    多年以來,IE一直都是最難于調(diào)試JavaScript 錯(cuò)誤的瀏覽器。IE給出的錯(cuò)誤消息一般很短又語焉不詳。而且上下文信息也很少,有時(shí)甚至一點(diǎn)都沒有。下面幾小節(jié)將分別探討一些在IE中難于調(diào)試的JavaScript 錯(cuò)誤
    2016-11-11
  • javascript?Echart可視化學(xué)習(xí)

    javascript?Echart可視化學(xué)習(xí)

    這篇文章主要為大家介紹了Echart可視化學(xué)習(xí)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • 手動(dòng)實(shí)現(xiàn)js短信驗(yàn)證碼輸入框

    手動(dòng)實(shí)現(xiàn)js短信驗(yàn)證碼輸入框

    本文記錄一下自己手動(dòng)實(shí)現(xiàn)的一個(gè)前端常見的短信驗(yàn)證碼輸入組件,從需求到實(shí)現(xiàn)逐步優(yōu)化的過程。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Knockout結(jié)合Bootstrap創(chuàng)建動(dòng)態(tài)UI實(shí)現(xiàn)產(chǎn)品列表管理

    Knockout結(jié)合Bootstrap創(chuàng)建動(dòng)態(tài)UI實(shí)現(xiàn)產(chǎn)品列表管理

    這篇文章主要為大家詳細(xì)介紹了Knockout結(jié)合Bootstrap創(chuàng)建動(dòng)態(tài)UI實(shí)現(xiàn)產(chǎn)品列表管理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • 微信小程序 數(shù)據(jù)緩存實(shí)現(xiàn)方法詳解

    微信小程序 數(shù)據(jù)緩存實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了微信小程序 數(shù)據(jù)緩存實(shí)現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • 使用原生js封裝的ajax實(shí)例(兼容jsonp)

    使用原生js封裝的ajax實(shí)例(兼容jsonp)

    下面小編就為大家?guī)硪黄褂迷鷍s封裝的ajax實(shí)例(兼容jsonp)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • js繪制圓形和矩形的方法

    js繪制圓形和矩形的方法

    這篇文章主要介紹了js繪制圓形和矩形的方法,涉及javascript鼠標(biāo)事件及頁面元素樣式的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-08-08
  • JS文件上傳時(shí)如何使用MD5加密

    JS文件上傳時(shí)如何使用MD5加密

    這篇文章主要介紹了JS文件上傳時(shí)如何使用MD5加密,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • JavaScript SHA-256加密算法詳細(xì)代碼

    JavaScript SHA-256加密算法詳細(xì)代碼

    這篇文章主要為大家詳細(xì)介紹了JavaScript SHA-256加密算法代碼,具有一定的參考價(jià)值,感興趣的朋友可以參考一下
    2016-10-10

最新評(píng)論

浦县| 遂宁市| 同心县| 桦甸市| 读书| 喀喇| 南宁市| 大兴区| 德庆县| 普宁市| 江门市| 普宁市| 吉安县| 乐平市| 兴化市| 安西县| 台南市| 贡嘎县| 团风县| 原平市| 麻栗坡县| 泰顺县| 元朗区| 石台县| 运城市| 翁牛特旗| 白河县| 济南市| 石家庄市| 华池县| 邯郸县| 东港市| 北海市| 获嘉县| 临高县| 三河市| 潼南县| 新巴尔虎左旗| 大英县| 务川| 游戏|