在移动页面开发中,经常需要封装一个描边层(全屏弹窗)、遮罩层(全屏弹窗)、遮罩层(全屏弹窗)组件,但如果是固定定位位置:fixed ; 弹出来的时候会遇到一些小坑。 之前搜了一下,无论是网上博客还是评论,总有一些缺陷或者代码太多遮挡眼睛。 比如明天的主题,如何防止描边层下面的正文内容(全屏弹窗)继续滚动?
移动端开发遮罩层(弹窗)防止滚动穿透的完美解决方案
首先PC端必须直接给body设置一个overflow:hidden属性,这是一个完美的解决方案。
这个没什么好说的css遮罩层,主要是在手机上,大家会发现给body添加的属性根本没有效果,还有遮罩层的时候怎么滑动或者怎么滑动(全屏弹窗)出现。
下面给出三种解决方案:
第一种解决方案(参考别人的解决方案):
点击弹出的时候,给html和body都添加overflow:hidden属性。 这时候你会发现背景不再滚动了,但是这样做有一个隐忧,那就是当遮罩层(全屏弹窗)消失的时候,页面会被手动返回至底部。 当有人浏览页面时,点击弹窗后消失然后返回底部? 显然不合理。 所以当你点击消失的时候,你得记录下当前的scrollTop,然后把形参给当前页面的scroll,就算解决了。 这里就不详细介绍写法了。 我推荐一个github作者来介绍这些技巧。 点击查看>>
ps:我个人认为这些方法也可以,但是代码太多,那就看下面的解决办法
第二种解决方案(适用于简单的弹窗):
直接在遮罩层(弹窗)上添加@touchmove.prevent(这里是vue中),它的作用是当你抚摸全屏层(弹窗)时,严禁滑动,原理是因为弹出层的滑动是严格禁止的。 自然就不存在滑动穿透的问题了。 是不是很简单粗暴呢? 我们想要做得更好的是给body添加一个overflow:hidden属性,这样人为的自动滑动就无法意外,也无法执行其他工具的滑动(鼠标)
document.body.classList.add('overflow-hidden');
.overflow-hidden{
overflow: hidden;
}
.box{
width: 100%;
height:100%;
position: fixed;
top: 0;
background: rgba(0,0,0,0.8);
}
第三种方案(适合封装组件,弹出时可以控制内容区域滚动的复杂情况):
点击弹窗时css遮罩层,监控touchmove风暴,严格禁止。
当点击消失时,听同样的风暴,删除删除。
这样做的用处在于,滑动风暴并不是在结构中直接禁用,而是通过指令控制,更适合开发需要。
click(){//点击弹窗
this.tan=true
document.body.classList.add('overflow-hidden');
document.addEventListener('touchmove', this.touchStart,{passive:false});//一般第三个参数可直接填false,true -> 表示在捕获阶段调用事件处理程序, false -> 表示在冒泡阶段调用事件处理程序使用,但是touchmove会被浏览器忽略掉,并不会阻止默认行为,这里通过passive:false明确声明为不是被动的
},
touchStart(){
event.preventDefault();//通知 Web 浏览器不要执行与事件关联的默认动作
},
close(){//点击关闭弹窗
this.tan=false
document.body.classList.remove('overflow-hidden');
document.removeEventListener('touchmove',this.touchStart,{passive:false});
}
你学会了吗? 帮您点赞加关注,有不懂或者不懂的欢迎留言。
最近在项目开发中遇到一个需求:页面左右布局分割线css,需要拖拽分割线实现手动适配长度。
解决方案
一般来说,在mounted生命周期中,监听分割线DOM的onmousedown,在拖拽过程中动态估计分割线css,然后用形参改变左右DOM元素的长度,就完成了。
模板部分:类为“touch-div”,即DOM的分割线。
<template>
<div class="wrap">
<div class="lf" ref="letfDom" style="width: 280px;">
<router-link to="/moreClick">moreClick</router-link>
<div class="touch-div" ref="moveDom">
<span></span>
<span></span>
</div>
</div>
<div class="rt">
<router-view />
</div>
</div>
</template>
CSS部分:cursor:col-resize; 可以实现键盘悬停时的左右箭头。
.wrap .lf .touch-div {
position: absolute;
top: 0;
height: 100%;
left: 100%;
width: 20px;
display: flex;
justify-content: center;
align-items: center;
cursor: col-resize;
}
.wrap .lf .touch-div span {
width: 2px;
background: #bbb;
margin: 0 2px;
height: 15px;
}
JavaScript部分
export default {
name: "App",
data() {
return {
letfDom: null,
clientStartX: 0
};
},
mounted() {
this.letfDom = this.$refs.letfDom;
let moveDom = this.$refs.moveDom;
moveDom.onmousedown = e => {
this.clientStartX = e.clientX;
e.preventDefault();
document.onmousemove = e => {
this.moveHandle(e.clientX, this.letfDom);
};
document.onmouseup = e => {
document.onmouseup = null;
document.onmousemove = null;
};
};
},
methods: {
moveHandle(nowClientX, letfDom) {
let computedX = nowClientX - this.clientStartX;
let leftBoxWidth = parseInt(letfDom.style.width);
let changeWidth = leftBoxWidth + computedX;
if (changeWidth < 280) {
changeWidth = 280;
}
if (changeWidth > 400) {
changeWidth = 400;
}
letfDom.style.width = changeWidth + "px";
this.clientStartX = nowClientX;
}
}
};
示例代码下载
您可以复制上面的代码并运行看看疗效,也可以去GitHub:下载,更多示例将持续更新,欢迎关注。
发表评论