遮罩层
1.如果将遮罩层直接放在body元素中,可以设置
position:absolute
,然后设置宽高撑满屏幕;此时position:absolute
相对于body进行绝对定位;
2.如果遮罩层不是body的直接子元素,可以设置position:fixed
,相对窗口进行定位
.mask1{
position: absolute;
height: 100%;
width: 100%;
background-color: #000;
opacity: 0.5;
}
.mask2{
position: fixed;
height: 100%;
width: 100%;
left: 0;
top: 0;
background-color: greenyellow;
opacity: 0.2;
}
- position:relative,相对定位,是指元素相对于正常文档流的位置进行定位;
1.不设置left/right或者bottom/top属性时,定位不生效;
2.只是位置相对发生变化,元素不会脱离文档流
3.元素设置相对定位后,会提高层级,可以覆盖相对于原本同级的元素
4.块级元素依旧是块级元素,行内元素依旧是行内元素;
- position:absolute,绝对定位,是指元素相对于最近一个position定位的元素进行绝对定位,如果在此之前没有positon定位的元素,则会一直寻找到body元素,并相对于body进行定位;
1.不设置left/right或者bottom/top属性时,定位不生效;
2.开启后,元素会脱离文档流;
3.元素属性可能发生变化,行内元素会变成块元素,块的宽高被内容撑开;
4.元素层级相对原本元素层级会提高;
5.absolute相对于最近的第一个position包含元素进行定位,如果没有,则以body为包含块进行定位;
- fixed定位,则是相对于窗口的定位,但是不要忘记设置left和top属性值,否则定位失效;
Modal层点击空白处触发事件
方法一:设置全局监听,判断监听的元素中是否含有内部元素
- 获取modal中的DOM元素,判断点击的元素是否包含该两个元素,因为点击任何一个元素不可能包含另一个元素,所以如果同时包含说明,点击的是最外层的遮罩;
- 关闭遮罩后记得清楚监听函数,否则产生内存泄漏
const clickHideMask = e => {
const eleBlockCenter = document.getElementsByClassName('detail-data');
const eleBlockRight = document.getElementsByClassName('detail-data-table');
// 获取modal中的DOM元素,判断点击的元素是否包含该两个元素,因为点击任何一个元素不可能包含另一个元素,所以如果同时包含说明,点击的是最外层的遮罩;
if (
e.target.contains(eleBlockCenter[0]) &&
e.target.contains(eleBlockRight[0])
) {
showMask(false); // 关闭遮罩层
}
};
// 关闭遮罩后记得清楚监听函数,否则产生内存泄漏
useEffect(() => {
if (maskVisible) {
document.body.addEventListener('click', clickHideMask);
} else {
document.body.removeEventListener('click', clickHideMask);
}
}, [maskVisible]);
// 相关元素
<div id="detail-wrap">
<div className="detail-data"></div>
<div className="detail-data-table"></div>
</div>
方法二:最外层设置点击事件,内部元素阻止冒泡;
DOM事件流中,点击modal中的元素,会冒泡到最外层元素中,此时只需要将包含元素禁止冒泡,就不会触发最外层的点击事件;
// 遮罩层内元素,阻止冒泡,最外层遮罩设置点击事件,触发关闭遮罩
< div
id="detail-wrap"
onClick={() => {
setExitCurrentPage(true);
showMask(false);
}}
>
<div
className="detail-data"
onClick={e => {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
}}
>
{maskBlock}
</div>
<div
className="detail-data-table"
onClick={e => {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
}}
>
</div>
</div>
Modal消失后触发其他事件
这种场景除了在一个点击事件中包含所有的事件处理方式之外,还可以将点击事件拆开,一个点击事件分为mousedown事件和mouseup事件,一个完整的click事件需要包含该两个事件;
<div class="bottom-wrap">
底部元素
<div class="div-wrap">
modal框
<div class="div-box1">元素一</div>
<div class="div-box2">元素二</div>
</div>
</div>
<script>
var a = document.querySelector('.div-wrap')
a.addEventListener('mouseup', function () {
a.style.visibility = 'hidden'
})
var b = document.querySelector('.bottom-wrap')
b.addEventListener('mousedown', function () {
b.style.background = 'pink'
})
</script>
如图点击事件拆分成mousedown和mouseup事件,同样也可以用这两种方法去做modal层的隐藏,但是依旧需要在元素上阻止冒泡