蒙版
在网页设计中,我们经常会使用到蒙版。所谓蒙版,顾名思义,就是“蒙在上面的一层板”。一般用黑色或添加品牌色的半透明遮罩效果,遮盖住下层界面,展示蒙版上层内容。
在引导说明、模态加载、模态弹窗等多种情况都会涉及到蒙版,今天浅谈一些我遇到的关于蒙版的问题,希望对你也有启发和帮助。
常规实现蒙版
实现
btn.addEventListener("click", fn);
function fn() {
let div = document.createElement("div");
body.appendChild(div);
div.classList.add("zhe");
let tl = document.createElement("div");
tl.innerHTML = `
<h3>${data.title}</h3>
<p>${data.content}</p>
<div class = 'dbtn'>
<button class = 'agree'>同意</button>
<button class = 'dis'>取消</button>
</div>
`;
div.appendChild(tl);
tl.classList.add("tlt");
let btn2 = tl.querySelectorAll("button");
for (let i = 0; i < btn2.length; i++) {
btn2[i].onclick = () => {
div.remove();
};
}
return false
}
实现效果是点击注册按钮,模拟生成一个蒙版(大div)与其中的免责声明(小div)
再次点击同意或取消,删除蒙版与免责声明div
问题
此种方式是最为常见的一种方式,但是当免责声明过长,有滚动条时,如果当免责声明的滚动条滚动到底部或者从底部滚到顶部的时候再继续滚动的话,蒙版下面的商城也是能够随滚动方向而滚动的,这样的交互效果不是很让人舒服。
目标效果
那我们想要实现的效果是出现蒙版和免责声明时,只允许免责声明中的内容滚动,而阻止蒙版后面的商城滚动
解决方案一
我们自然而然会想到,当出现弹窗时,我阻止body的浏览器默认行为就好了,这样就滚动不了了,有想法我们就来试试是否可行吧。
btn.addEventListener("click", fn);
function fn() {
//添加了一个阻止默认行为的函数
function fn(e) {
e.preventDefault()
}
//当点击生成蒙版时,同时给body增加一个禁止滚动事件
body.addEventListener('wheel', fn)
let div = document.createElement("div");
body.appendChild(div);
div.classList.add("zhe");
let tl = document.createElement("div");
tl.innerHTML = `
<h3>${data.title}</h3>
<p>${data.content}</p>
<div class = 'dbtn'>
<button class = 'agree'>同意</button>
<button class = 'dis'>取消</button>
</div>
`;
div.appendChild(tl);
tl.classList.add("tlt");
let btn2 = tl.querySelectorAll("button");
for (let i = 0; i < btn2.length; i++) {
btn2[i].onclick = () => {
div.remove();
//去除蒙版时,移出给body添加的静止滚动事件
body.removeEventListener('wheel', fn)
};
}
return false
}
结果如何呢?当我生成蒙版,鼠标放到蒙版后面的商城范围滚动时,并未实现禁止滚动,而且报了很多错
‘Unable to preventDefault inside passive event listener due to target being treated as passive’
滚动一次报一下错误,这是为何呢?
属性passive
1.passive是个啥?
passive是监听事件时候新增的一个选项
addEventListener(type, listener, {
capture: false,
passive: false,
once: false
})
第三个参数是一个对象,有三个属性,其中第二个passive就是要说的。
2.passive有什么作用?
passive就是为了改善移动端滚屏性能而设计的
当我们去滚动页面时,浏览器是在不断重新绘制的,因为无论滑动多少,视口里面显示的东西都不一样。而这种重新绘制是需要耗时的,所以passive就是其中浏览器用来优化绘制的其中之一。
但优化的条件是你得保证不去阻止浏览器默认行为,若是你阻止了默认行为(意思是将passive:false),但是你又并未明确在绑定监听事件的第三个参数处将passive设为false,起了冲突,所以报错。
3.解决问题
body.addEventListener('wheel', fn, { passive: false })
新的问题
将body的默认行为阻止了,此时免责声明中的滚动也被静止了,得不偿失了,不是我们想要的效果。
解决方案二
function fn() {
//给body添加一个class(overflow: hidden)
body.classList.add('hidden')
let div = document.createElement("div");
body.appendChild(div);
div.classList.add("zhe");
let tl = document.createElement("div");
tl.innerHTML = `
<h3>${data.title}</h3>
<p>${data.content}</p>
<div class = 'dbtn'>
<button class = 'agree'>同意</button>
<button class = 'dis'>取消</button>
</div>
`;
div.appendChild(tl);
tl.classList.add("tlt");
let btn2 = tl.querySelectorAll("button");
for (let i = 0; i < btn2.length; i++) {
btn2[i].onclick = () => {
div.remove();
//给body移除class(overflow: hidden)
body.classList.remove('hidden')
};
}
return false
}
当生成蒙版时,将背后商城的超出部分‘剪切’掉,此时就没有滚动条了,实现了免责声明内容可滚动而蒙版后的商城不可滚动。
当删除蒙版时,再将body的overflow: hidden删除,恢复正常。