我们在做移动端项目开发时,经常会遇到弹框不能锁定背景的背景的问题。比如有一个站视规则并且可以滚动的弹框,这是我们滑动滚动条浏览更多内容的时候,页面会跟随着一起滑动,这种体验不太友好。那么如何解决呢?
html、body设置hidden
我们可以设置html和body的overflow为hidden,1
2
3
4.lock{
height: 100%;
overflow: hidden;
}
当弹框展现时,我们可通过js为html和body加上类名,弹框隐藏时,移除类名lock
。一些ui框架的弹框也是采用这种方法,如vant
的popup
弹出层组件。但是这种方法并不能在所有的移动设置生效。
阻止touchmove默认事件
为 body 绑定 touchmove 事件,然后调用 preventDefault() 方法,禁止 touchmove 的默认行为。1
2
3
4
5
6
7
8
9function preventDefaultFn(event){
event.preventDefault();
}
// 弹出时
$('body').on('touchmove', preventDefaultFn);
// 隐藏时
$('body').off('touchmove', preventDefaultFn);
如果是vue的项目,有一个更简洁的方式,在弹框的遮罩层加上`@touchmove.prevent`即可1
<div class="mask" @touchmove.prevent>
但这种方法有一定的局限性,它适合于弹框内的元素不发生滚动,如果弹框的内容需要滚动,那么这种方法就不行了,滚动的内容无法继续滚动了,当然我们可以通过js模拟滚动,不过这有些麻烦。还好我们有第三种方案。
设置body为fixed定位
监听页面弹框的显现与隐藏,当页面有弹框出现时,我们将body设为fixed
定位,然后设置 top 为页面滚动的高度,弹框隐藏时移除 body 的 fixed 定位,并把页面重新滚动到之前的位置。下面时我在vue项目
中解决body随弹框滚动的问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24watch:{
// visible是页面中用来控制弹框显示与隐藏的变量集合
visible: {
deep: true,
handler(newval) {
const hasPoup = Object.values(newval).some(val => val == true);
// 如果有弹框显示
if (hasPoup) {
pageTop =
document.documentElement.scrollTop || document.body.scrollTop;
// body 为 fixed定位
document.body.classList.add("body-fixed");
// 设置页面位置
document.body.style.top = `-${pageTop}px`;
} else {
// 弹框隐藏
document.body.classList.remove("body-fixed");
document.body.style.top = `0rem`;
window.scrollTo(0, pageTop);
}
},
immediate: true
}
}
1 | .body-fixed { |