欢迎测评:前端工程师
在页面上加些代码,让页面白屏幕,有哪些方式呢?如何防御呢?
本文介绍了 8 种让页面白屏的方法。在防御方法中,包含了一些你可能不知道的冷知识,如:判断元素是否被遮挡。
方法1: 隐藏根节点
html {
display:none !important;
}
选择器用 body 也能达到一样的效果。
当页面是深色模式时,添加上面的代码页面后,页面是黑色的。需要取消深色模式:删除下面的代码:
<meta name="color-scheme" content="dark" >
方法2: 让根节点不可见
设置可见性的属性:
html {
visibility: hidden !important;
}
或者,设置透明度为完全透明:
html {
opacity: 0 !important;
}
方法3: 大小设为0,超出隐藏
body {
width: 0 !important;
height: 0 !important;
overflow: hidden !important;
}
选择器用 html 没有效果。
方法4: 偏移出屏幕
用 fixed 定位:
html {
position: fixed;
left: -99999px;
}
或者,用 transform:
html {
transform: translateX(-99999px);
}
方法5: 遮挡页面
用全屏的白色元素遮挡页面。
html::before {
content: '';
position: fixed;
z-index: 999999;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: #fff;
}
方法6: 缩小
html {
transform: scale(0.0000000000001);
}
方法7: 清空页面内容
document.documentElement.innerHTML = ''
方法8: 页面跳转到一个空白页面
location.href = '空白页面URL'
这个方法有点皮~
防御
检测白屏的样式
通过轮训检查根节点上,是否有导致白屏的样式。如果有,则刷新页面。例如:
setInterval(() => {
if(hasWhitePageStyle()) {
location.reload()
}
}, 100)
通过这种方式,可以防御方法 1 ~ 6。我们来看具体的检查方法。
根节点是否隐藏检查
const root = document.documentElement
const body = document.body
if(
getComputedStyle(root, null).display === 'none' ||
getComputedStyle(body, null).display === 'none'
) {
return true // 根节点被隐藏
}
根节点是否可见检查
if(
getComputedStyle(root, null).visibility === 'hidden' ||
getComputedStyle(body, null).visibility === 'hidden'
) {
return true // 不可见
}
if(
getComputedStyle(root, null).opacity < 0.1 ||
getComputedStyle(body, null).opacity < 0.1 ||
) {
return true // 不可见
}
大小为 0 检查
const {width, height } = body.getBoundingClientRect()
if(width === 0 || height === 0) {
return true // 大小为 0
}
偏移出屏幕检查
const {left, right, top, bottom } = body.getBoundingClientRect()
if(
left > window.innerWidth ||
right < 0 ||
top > window.innerHeight ||
bottom < 0
) {
return true // 偏移出屏幕
}
遮挡检查
document.elementFromPoint(x, y)[1] 返回某个坐标点下最上层的元素。如果元素没有被遮挡,则在该 API 中传入元素的上下左右四个坐标点,返回的均为该元素。
假设页面上有个 id 为 tar 的元素,如果该元素未被遮挡,则认为页面被遮挡。
const tarElem = document.getElementById('tar')
const {left, right, top, bottom} = tarElem.getBoundingClientRect()
if(
document.elementFromPoint(left, top) === tar &&
document.elementFromPoint(left, bottom) === tar &&
document.elementFromPoint(right, top) === tar &&
document.elementFromPoint(right, bottom) === tar &&
) {
return true// 未被遮挡
}
防止修改 DOM
MutationObserver API[2] 可以监控 DOM 的变动。用该 API 可以防御页面内容被清空。代码如下:
// 监控 属性,子节点和后代节点的变动
const config = { attributes: true, childList: true, subtree: true };
const observer = new MutationObserver((mutationsList) => {
for(let mutation of mutationsList) {// 页面DOM变动
location.reload()
}
})
window.addEventListener('DOMContentLoaded', () => {
observer.observe(document.documentElement, config);
})
防止页面跳转
目前没有找到防御的方法。尝试过以下方法。
重置 window.location
执行:
window = {}
window.location 仍然在。
执行:
const location = ''
和
function location () {}
都会报错。
执行:
window.location = {}
页面直接跳转了。
将 window.location 设置为只读
做了如下尝试,均不行:
Object.freeze(window) // 报错
Object.freeze(window.location) // 无效
// 报错
Object.defineProperty(window, "location", {"writable": false})
// 报错
Object.defineProperty(location, "false", {"writable": false})