Javascript 防止Safari自动滚动到焦点元素(在Safari 12中,回滚技术停止工作)

Javascript 防止Safari自动滚动到焦点元素(在Safari 12中,回滚技术停止工作),javascript,macos,safari,Javascript,Macos,Safari,Safari for desktop自动将页面滚动到我从javascript关注的任何输入元素。这种行为可以在这里看到: 我没有找到办法阻止这种自动滚动。但是,有一个已知的解决方法-先保存屏幕位置,然后在对焦后滚动回该位置: var el = document.getElementById("editable"); var x = window.scrollX, y = window.scrollY; // save position el.focus(); // manipulate sel

Safari for desktop自动将页面滚动到我从javascript关注的任何输入元素。这种行为可以在这里看到:

我没有找到办法阻止这种自动滚动。但是,有一个已知的解决方法-先保存屏幕位置,然后在对焦后滚动回该位置:

var el = document.getElementById("editable");
var x = window.scrollX, y = window.scrollY; // save position
el.focus();
// manipulate selection inside the focused element with `document.createRange()`
// and do other stuff
window.scrollTo(x, y); // restore position
该解决方案在Safari 10中工作正常,在Safari 12中停止工作。聚焦后调用
scrollTo
将不再起任何作用。但是,如果执行
scrollTo
时有延迟(即使是很短的延迟),则一切正常:

var el = document.getElementById("editable");
var x = window.scrollX, y = window.scrollY; // save position
el.focus();
// manipulate selection inside the focused element with `document.createRange()`
// and do other stuff
setTimeout(function() {
    window.scrollTo(x, y); // restore position
}, 1);
但是,有了1毫秒的延迟,你可以看到页面首先滚动到输入字段,然后很快回到原来的位置,因此新的解决方法还远远不够完美


有没有什么方法可以优雅地防止桌面Safari自动将页面滚动到焦点元素,或者至少有一个很好的解决方案来缓解这种行为?

经过多次尝试,我终于找到了一个有效的解决方案:

var el = document.getElementById("editable");
var scrollTop = document.body.scrollTop; // save position
el.focus();
// manipulate selection inside the focused element with `document.createRange()`
// and do other stuff
document.body.scrollTop = scrollTop;

出于某种原因,保存
document.body.scrollTop
有效,而保存
window.scrollX
window.scrollY不起作用。

我刚刚遇到了同样的错误,并且能够让我的版本使用:

setTimeout(function() {
    window.scrollTo(x, y);
}, 0);
我认为在Safari 12中(出于某种原因),HtmleElement Web API中的focus方法比Window Web API中的scrollTo方法运行时间更长。如果是这种情况,那么在焦点方法的完成和scrollTo方法之间就会出现竞争条件,导致滚动位置停留在焦点元素上

使用延迟为0ms的setTimeout实际上只是说“一旦调用堆栈中的所有内容都执行完毕,就运行它”,这似乎为我解决了这个问题

以下是调试时用作资源的视频:

希望这有帮助