angualr1.x,bootstrap/modal.js@v3.3.7瀏覽器回退操作modal遮罩未消失

前言

本文所陳述的問題解決方案是技術棧基于angualr1.x,bootstrap/modal.js@v3.3.7版本下,所處理的問題。(項目中遇到的一個問題,作以記錄。)

什么樣的問題?

在基于上文所述的技術棧上所做的一個web端項目,在測試時被提出在有彈窗的界面上調出modal層,然后點擊瀏覽器上的回退按鈕。這個時候問題就來了,頁面雖然成功返回至上一頁,modal層卻依然存在。。。

如何解決?

在接到提出的問題后,考慮如何去解決。

1,首先,使用過bootStrap的modal.js的童鞋應該都知道其提供給我們手動操作modal層打開,關閉的api如下:

打開id為"testModal"的modal層


    $('#testModal').modal('show')

關閉modal層


    $('#testModal').modal('hide')

所以呢我的第一想法就是在點擊瀏覽器回退按鈕時,去關閉掉所有的modal那么問題不就解決了嗎?

2,監聽瀏覽器點擊回退按鈕觸發事件


    $(document).ready(function(e) {
        if (window.history && window.history.pushState) {
            //每當處于激活狀態的歷史記錄條目發生變化時,popstate事件就會在對應window對象上觸發
            // popstate事件只會在瀏覽器某些行為下觸發, 比如點擊后退、前進按鈕(或者在JavaScript中調用history.back()、history.forward()、history.go()方法).
            window.onpopstate = function () {
                // 此處進行你想要的操作
            }
        }
    }

3,瀏覽器的回退監聽也有了,modal的關閉方法也有了,那么問題是不是就解決了呢?此處提下,每個調出的modal層都具有一個共同的class即 "modal"。一般我們會給不同的modal層賦予不同的id通過id操作modal層的展示與否。而通過class亦可同樣控制。


    $(document).ready(function(e) {
        if (window.history && window.history.pushState) {
            //每當處于激活狀態的歷史記錄條目發生變化時,popstate事件就會在對應window對象上觸發
            // popstate事件只會在瀏覽器某些行為下觸發, 比如點擊后退、前進按鈕(或者在JavaScript中調用history.back()、history.forward()、history.go()方法).
            window.onpopstate = function () {
                // 此處進行你想要的操作
                $(".modal").modal('hide')
            }
        }
    }

4,理論上到此就應該結束了,然鵝并木有。實際運行過程中,你會發現在執行到

$(".modal").modal('hide')

的時候,window.history亦發生了變化,原本的預期想要關閉的modal層dom結構已經不存在了!!!但是調用modal層伴隨的遮罩卻依然存在。。。

這個時候有小伙伴說了,那你直接將modal層的遮罩在回退觸發的時間里面remove掉不就ok了嗎?

是的,我也是這樣想的。于是代碼變成了醬紫

提一下,modal彈層調用時所附帶的遮罩層所具有的class為 "modal-backdrop"


    $(document).ready(function(e) {
        if (window.history && window.history.pushState) {
            //每當處于激活狀態的歷史記錄條目發生變化時,popstate事件就會在對應window對象上觸發
            // popstate事件只會在瀏覽器某些行為下觸發, 比如點擊后退、前進按鈕(或者在JavaScript中調用history.back()、history.forward()、history.go()方法).
            window.onpopstate = function () {
                // 此處進行你想要的操作
                $(".modal-backdrop").remove()
            }
        }
    }

5, 萬事大吉,打完收工?那是不可能的。如上操作之后,果然如預期一般再也沒有黑糊糊的一層面紗遮擋我們的實現了。but你有木有發現你的頁面不能滾動了!!!我去!remove了一個遮罩怎么就不能滾動了呢?

于是乎,我想起來了源碼。這個時候去看一眼源碼對于modal層的展示與關閉到底做了什么操作?

相關源碼如下:

modal.show()


    Modal.prototype.show = function (_relatedTarget) {
        var that = this
        var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })

        this.$element.trigger(e)

        if (this.isShown || e.isDefaultPrevented()) return

        this.isShown = true

        this.checkScrollbar()
        this.setScrollbar()
        this.$body.addClass('modal-open') // 注意這里,show()的時候給我們的頁面添加了一個 "modal-open"的類名

        this.escape()
        this.resize()

        this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))

        this.$dialog.on('mousedown.dismiss.bs.modal', function () {
          that.$element.one('mouseup.dismiss.bs.modal', function (e) {
            if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
          })
        })

        this.backdrop(function () {
          var transition = $.support.transition && that.$element.hasClass('fade')

          if (!that.$element.parent().length) {
            that.$element.appendTo(that.$body) // don't move modals dom position
          }

          that.$element
            .show()
            .scrollTop(0)

          that.adjustDialog()

          if (transition) {
            that.$element[0].offsetWidth // force reflow
          }

          that.$element.addClass('in')

          that.enforceFocus()

          var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })

          transition ?
            that.$dialog // wait for modal to slide in
              .one('bsTransitionEnd', function () {
                that.$element.trigger('focus').trigger(e)
              })
              .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
            that.$element.trigger('focus').trigger(e)
        })
    }

Modal.hide()


    Modal.prototype.hide = function (e) {

        if (e) e.preventDefault()

        e = $.Event('hide.bs.modal')

        this.$element.trigger(e)

        if (!this.isShown || e.isDefaultPrevented()) return

        this.isShown = false

        this.escape()
        this.resize()

        $(document).off('focusin.bs.modal')

        this.$element
          .removeClass('in')
          .off('click.dismiss.bs.modal')
          .off('mouseup.dismiss.bs.modal')

        this.$dialog.off('mousedown.dismiss.bs.modal')

        $.support.transition && this.$element.hasClass('fade') ?
          this.$element
            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
            .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
          this.hideModal() // 這里我們看到在執行hide時調用了hideModal()的方法
  }

hideModal()


    Modal.prototype.hideModal = function () {
        var that = this
        this.$element.hide()
        this.backdrop(function () {
          that.$body.removeClass('modal-open') // 清除添加在body上的類名
          that.resetAdjustments()
          that.resetScrollbar()
          that.$element.trigger('hidden.bs.modal')
        })
    }

那么這個類名有做了些什么呢?我們看一下


    .modal-open {
        overflow: hidden;
    }

沒有錯,就是它限制了我們的頁面滾動。那么剩下的就好辦了


    $(document).ready(function(e) {
        if (window.history && window.history.pushState) {
            //每當處于激活狀態的歷史記錄條目發生變化時,popstate事件就會在對應window對象上觸發
            // popstate事件只會在瀏覽器某些行為下觸發, 比如點擊后退、前進按鈕(或者在JavaScript中調用history.back()、history.forward()、history.go()方法).
            window.onpopstate = function () {
                // 此處進行你想要的操作
                $("body").removeClass("modal-open")
                $(".modal-backdrop").remove()
            }
        }
    }

6, ok ...這次是真的結束了。。。純屬個人淺見。如有更好解決方案歡迎賜教。


created by 18/11/06

author by sparkc

email 1948559620@qq.com

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,771評論 25 708
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,815評論 2 59
  • 這個世界上肯定有另一個我,做著我不敢做的事,生活成了我喜歡的樣子。 另一個自己: 我一直都很羨慕你,我喜歡的每一個...
    親愛的山南水北閱讀 499評論 0 5
  • 下載地址:dome無UI界面設計 核心代碼 參考文獻什么是 CGConTextRef
    黎希閱讀 1,891評論 0 0
  • 文案策劃的書寫,不能簡簡單單的只是寫幾個字,將產品信息,優惠信息,活動內容表達清楚就可以了,文案策劃的下一步就是對...
    正能量小鵬勵志語錄閱讀 152評論 0 0