JS Idiomatic alert()而不搞砸HTML渲染



摘要

我正在编写带有大量警报/确认的代码,我发现保持所有内容的呈现方式很痛苦。我只想让下面的片段按预期工作。第一";在">,然后等待用户确认警报框。然后";在">

document.getElementById('display').innerHTML = "Before";
// ALERT
document.getElementById('display').innerHTML = "After";

已尝试

我尝试过天真的方式&建议使用CCD_ 1在SO上执行一百万次重复操作。(我尝试了零和非零time。(

document.getElementById('display').innerHTML = "Before";
alert("Alert Text")
document.getElementById('display').innerHTML = "After";
document.getElementById('display').innerHTML = "Before";
setTimeout(function() {
alert("Alert Text")
}, time);
document.getElementById('display').innerHTML = "After";

在第一种情况下,在警报停止执行之前,之前的内容尚未完成渲染。在第二个场景中,下面的东西已经开始渲染,取代了上面的东西。

想法

可以在setTimeout()块中将任何东西放在警报之下。对于一个警报来说,这不是一个可怕的黑客攻击。但是有很多警报,这意味着有很多嵌套的setTimeout(),这在几个层面上似乎是错误的!

一个简单的sleep()可以解决所有问题。但接受的SO答案警告永远不要在JS中使用sleep()等价物,而更喜欢setTimeout()。所以回到原点1!

TL;DR:使用alert()的最佳方式是什么;之后按顺序呈现

不要使用alert()或任何其他提示,甚至不要用于调试
这些都是web API的旧工件,不应该再使用了。

它们有一个非常奇怪的特性,即阻塞当前的js执行直到关闭。不同的浏览器会以不同的方式处理它,例如在Firefox中;旋转事件循环";当类似的事情发生时,让事件循环的渲染部分仍然有效,因此在该浏览器中,您将看到绘制的更新值。然而,在Chrome中,它们会完全锁定事件循环,并且不会发生渲染。

因此,解决方案是永远不要依赖这些方法,而是使用HTML和CSS构建自己的模态。HTML中有一个setTimeout()0元素,它在从头开始执行这种模式时有很大帮助,但任何UI库都有自己的模式(示例(。

然后,您只需要监听close事件或等效事件,就可以知道用户何时关闭了该模式:

const dial = document.getElementById("dial");
document.getElementById("display").textContent = "Before";
dial.showModal();
console.log("js execution is not blocked");
// when the modal is closed
dial.addEventListener("close", (evt) => {
document.getElementById("display").textContent =
"After";
}, { once: true });
<div id="display"></div>
<dialog id="dial">
<form method="dialog">
<p>My awesome alert message</p>
<button value="default">OK</button>
</form>
</dialog>

如果你需要一种比所有这些回调更线性的编码方式,你可以随时承诺并使用异步/等待函数:

const dial = document.getElementById("dial");
function myAlert(message) {
dial.querySelector("p").textContent = message;
dial.showModal();
return new Promise( (res) => {
dial.addEventListener("close", () => res(), { once: true });
});
}
(async () => {
document.getElementById("display").textContent = "Before";
await myAlert('hello');
document.getElementById("display").textContent = "After";
await myAlert('bye');

})();
dialog {
min-width: 150px;
}
dialog > form > button {
float: right;
}
<div id="display"></div>
<dialog id="dial">
<form method="dialog">
<p>My awesome alert message</p>
<button value="default">OK</button>
</form>
</dialog>

最新更新