1. 程式人生 > >跳出彈窗頁面禁止滾動(PC端和手機端)

跳出彈窗頁面禁止滾動(PC端和手機端)

pc端如何實現

1.當彈窗顯示時,為body元素新增屬性:overflow:hidden, 當關閉彈窗時移除該屬性即可
2.在彈窗的div上設定 @scroll.stop.prevent

<div @scroll.stop.prevent>
 你要顯示的內容
</div>

3.出現彈窗時,為body元素新增position:fixed,這樣主頁面就禁止滑動,同時很好地解決了彈窗穿透的問題。
若彈窗為獨立元件,可以採用如下程式碼:

beforeMount() {
    // 獲取原來的scrollTop 並將body的top修改為對應的值
    this.prevBodyStyle_scrollTop = document.body.scrollTop || document.documentElement.scrollTop
    this.prevBodyStyle_top = window.getComputedStyle(document.body, null).getPropertyValue('top')
    document.body.style.top = `-${this.prevBodyStyle_scrollTop}px`
    // 獲取原來body的position 為了解決iOS上游標漂移的問題 將position修改為fixed
    this.prevBodyStyle_position = window.getComputedStyle(document.body, null).getPropertyValue('position')
    document.body.style.position = 'fixed'
    // 為了避免width空值的情況
    this.prevBodyStyle_width = window.getComputedStyle(document.body, null).getPropertyValue('width')
    document.body.style.width = '100%'
  },

  beforeDestroy() {
    document.body.style.top = this.prevBodyStyle_top || '0px'
    document.body.style.position = this.prevBodyStyle_position
    document.body.style.width = this.prevBodyStyle_width || '100%'
    document.body.scrollTop = document.documentElement.scrollTop = this.prevBodyStyle_scrollTop || 0
  },

備註: 如果彈窗為一個獨立的元件, 那麼需要使用v-if來控制彈窗是否顯示,不可使用v-show(因為使用v-show,會在主頁面剛生成的同時生成該元件,導致position=fixed生效,在彈窗關閉的情況下頁面也禁止滑動)

移動端如何實現

1.在彈窗的最外層div上新增@touchmove.stop.prevent (適合彈窗內容不需要滾動的情況下)

<div @touchmove.stop.prevent>
 你要顯示的內容
</div>

存在問題: 雖然可以阻止滑動,但是雙擊的時候主頁面還是會跳動

2.同PC端第三種方法
3.通過addEventListener解決

mounted() {
        document.body.addEventListener('touchmove', this.p, {passive: false})  
    },
beforeDestroy () {
      document.body.removeEventListener('touchmove', this.p)
    },
methods: {
    p (e) {
         e.preventDefault()
          e.stopPropagation()
      } 
}

劃重點:addEventListener的第三個引數 {passive: false}

先說說錯誤的程式碼,網上千篇一律的都是怎麼成功的,納悶了,反正我沒有成功,在手機端和chrome瀏覽器等依然可以正常滾屏:

document.body.addEventListener("touchstart",function(e){
                    e.stopPropagation();
                    e.preventDefault();
                },false);

錯誤程式碼為什麼不行呢,而為什麼使用{passive: false}就生效了呢?
摘自MDN的解釋:

passive: Boolean,表示 listener 永遠不會呼叫preventDefault()。如果 listener 仍然呼叫了這個函式,客戶端將會忽略它並丟擲一個控制檯警告。

MDN對於上述錯誤現象解釋地很清楚:

根據規範,passive 選項的預設值始終為false。但是,這引入了處理某些觸控事件(以及其他)的事件監聽器在嘗試處理滾動時阻止瀏覽器的主執行緒的可能性,從而導致滾動處理期間效能可能大大降低。
為防止出現此問題,某些瀏覽器(特別是Chrome和Firefox)已將touchstart和touchmove事件的passive選項的預設值更改為true文件級節點 Window,Document和Document.body。這可以防止呼叫事件監聽器,因此在使用者滾動時無法阻止頁面呈現。
var elem = document.getElementById('elem'); 
elem.addEventListener('touchmove', function listener() { /* do something */ }, { passive: true });
新增passive:true引數後,touchmove事件不會阻塞頁面的滾動(同樣適用於滑鼠的滾輪事件)。

所以,我們可以通過將passive的值顯式設定為false來覆蓋此行為。

另外:您無需擔心基本scroll 事件的passive值。由於無法取消,因此事件監聽器無法阻止頁面呈現。(也是在PC端監聽scroll無效的原因)

參考連結

前兩種方法:https://blog.csdn.net/Chelle1...
第三種:https://blog.csdn.net/yuhk231...
vue prevent方法: https://www.cnblogs.com/Eden-...
mdn關於addEventListener: https://developer.mozilla.org...

原文地址:https://segmentfault.com/a/1190000017217663