html 更新元素< progress>在Chrome中有效,但在Safari中无效

kcwpcxri  于 2023-05-27  发布在  其他
关注(0)|答案(1)|浏览(137)

我正在尝试从异步函数中更新进度条。下面的代码片段在Chrome中适用,但在Safari中不适用:

<!DOCTYPE html>
<html>

<body>
  <progress id="progressBar" value="40" max="100"></progress>
  <script>
    (async () => {
      const progressBar = document.getElementById("progressBar");
      for (let i = 0; i <= 100; i++) {
        progressBar.value = i;
        await new Promise(resolve => setTimeout(resolve, 100)); // sleep for 0.1s
      }
    })();
  </script>
</body>

</html>

在chrome中,进度条每0.1秒更新一次。
在Safari中,进度条不会更新(循环执行,我们甚至可以看到progressBar的值正在通过打印console.log(progressBar.value)进行更新,但该更改不会反映在UI中)。
我使用的是M1 Macbook Pro和Safari Version 16.4 (18615.1.26.11.23)

bvhaajcl

bvhaajcl1#

我可以在当前的稳定版本16.4(18615.1.26.110.1)上重现相同的bug,但在最新的技术预览版(Release 170(Safari 16.4,WebKit 18616.1.14.5))上却无法重现。所以我想我们可以假设他们已经修复了它,我们所要做的就是等待稳定的修复。
如果你需要一个解决方法,一个似乎有效的方法是强制在DOM中重新插入元素:

(async () => {
  const progressBar = document.getElementById("progressBar");
  for (let i = 0; i <= 100; i++) {
    progressBar.value = i;
    // workaround Safari bug not updating the UI
    progressBar.replaceWith(progressBar);
    await new Promise(resolve => setTimeout(resolve, 100)); // sleep for 0.1s
  }
})();
<progress id="progressBar" value="40" max="100"></progress>

因为设置<progress>元素的.value IDL属性也会设置它的value=""内容属性,这应该没有听起来那么糟糕,因为设置IDL属性无论如何都会触发内容属性的DOM变化记录,所以我们只是在同一个变化事件中将其叠加起来。

相关问题