前言
本文所陈述的问题解决方案是技术栈基于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
网友评论