(一) 前言
说来真是搞笑,之前很多交互都是依赖UI库的modal实现,之前也遇到过类似天猫商品列表页面那种下拉筛选,也解决过相关手势问题,但是,后面一个同事再次问起这个问题,回头去总结下,发现之前通过选取dom并为背景和内容分别处理touchmove事件,但是这仅仅是对于h5的一个解决方案,所以总结常见在pc/h5上面分别的处理方案。
(二) PC处理方案
打开蒙层时,给body添加样式:
overflow: hidden;
height: 100%;
- 1
- 2
在某些机型下,你可能还需要给根节点添加样式:
overflow: hidden;
- 1
关闭蒙层时,移除以上样式。
优点:
简单方便,只需添加css样式,没有复杂的逻辑。
缺点:
兼容性不好,适用于pc,移动端就尴尬了。
部分安卓机型以及safari中,无法无法阻止底部页面滚动。
如果需要应用于移动端,那么你可能需要方案二。
(三) 移动端处理方案
移动端可以直接阻止冒泡方式,处理这个问题,
const preventFun = e => ();
export function handleStopTouch() {
('touchmove', preventFun, { passive: true });
}
export function handleOpenTouch() {
('touchmove', preventFun, { passive: false });
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
但是上面方式是直接阻止来所有的事件,所以如果内容需要滚动,就需要如下的方案
移动端类似抽屉这种,有两部分组成,一个蒙层,一个内容区域,因为内容区域需要滚动,所以我们的touch事件应该绑定在蒙层区域,类似如下
// 抽屉drawer处理滚动穿透
const preventFun = e => ();
export function noScroll(isInScroll = false) {
('.am-drawer-overlay').addEventListener('touchmove', preventFun, { passive: false });
if (!isInScroll) {
('.am-drawer-sidebar').addEventListener('touchmove', preventFun, { passive: false });
}
}
export function noScrollClose(isInScroll = false) {
('.am-drawer-overlay').removeEventListener('touchmove', preventFun, { passive: true });
if (!isInScroll) {
('.am-drawer-sidebar').removeEventListener('touchmove', preventFun, { passive: true });
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
(四) PC/H5兼容方案
既然我们要阻止页面滚动,那么何不将其固定在视窗(即position: fixed),这样它就无法滚动了,当蒙层关闭时再释放。
当然还有一些细节要考虑,将页面固定视窗后,内容会回头最顶端,这里我们需要记录一下,同步top值。
// 处理手势
export const modalHelper = {
bodyEl: ,
top: 0,
handleStopScroll() {
= ;
= 'fixed';
= `${-}px`;
},
handleOpenScroll() {
= '';
= '';
(0, ); // 回到原先的top
},
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16