【发布时间】:2017-06-09 12:00:12
【问题描述】:
我做了这个pen 来模拟这个问题。
function createBox() {
var box = document.createElement("div");
box.className = "box";
box.style.backgroundColor = "#"+((1<<24)*Math.random()|0).toString(16);
return box;
}
function prependInnerHTML() {
console.log('prependInnerHTML');
var element = document.getElementById('scroll');
var box = createBox();
element.innerHTML = box.outerHTML + element.innerHTML;
element.prepend(box);
}
function prependPrepend() {
console.log('prependPrepend');
var element = document.getElementById('scroll');
var box = createBox();
element.prepend(box);
}
function prependPrepend() {
console.log('prependPrepend');
var element = document.getElementById('scroll');
var box = createBox();
element.prepend(box);
}
function prependInsertBefore() {
console.log('prependInsertBefore');
var element = document.getElementById('scroll');
var box = createBox();
element.insertBefore(box, element.firstChild);
}
function scroll() {
console.log('scroll');
var detailElement = document.getElementById('details');
var scrollElement = document.getElementById('scroll');
detailElement.innerHTML = "ScrollTop: " + scrollElement.scrollTop;
}
function clearScrollElement() {
console.log('clear');
var element = document.getElementById('scroll');
while(element.firstChild){
element.removeChild(element.firstChild);
}
}
html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%
}
#details {
position: fixed;
top: 10px;
left: 20px;
background-color: white;
}
#options {
position: fixed;
top: 10px;
right: 20px;
background-color: white;
}
#scroll {
overflow-x: hidden;
overflow-y: scroll;
height: 100%;
width: 100%;
}
.box {
height: 100vh;
width: 100%
}
<div id="options">
<span onclick="prependInnerHTML()">InnerHTML</span>
<span onclick="prependInsertBefore()">InsertBefore</span>
<span onclick="prependPrepend()">Prepend</span>
<span onclick="clearScrollElement()">Clear</span>
</div>
<div id="details">
ScrollTop: 0
</div>
<div id="scroll" onscroll="scroll()"></div>
问题是当一个元素被附加到一个可滚动元素时,它在不同的浏览器中会有不同的行为。
innerHTML:
第一个 prepend 方法是改变可滚动元素的 innerHTML。这似乎在多个浏览器中是一致的。
问题是像 Vue 这样的框架在内部没有使用这种方法,它可能使用其他方法之一。
使用 Chrome 插入之前:
如果 scrollTop 为 0 并且我们预先设置 scrollTop 保持为零。如果 scrollTop 大于零,它将调整 scrollTop 以包含前置元素的高度。
在 IE/Edge/Firefox 中插入之前:
与 innerHTML 的行为相同。
前置:
在 IE/Edge 上似乎不支持 Prepend,所以我会跳过那个。
问题:
如何在不引入各种浏览器检查的情况下使 InsertBefore 在所有浏览器中表现相同?
【问题讨论】:
-
听起来像是 chrome 的滚动锚定。我相信自 v56 以来它现在默认开启。您可以尝试将其关闭以查看是否可以使浏览器之间的行为正常化,然后从那里开始。您可以在这里阅读一些相关信息:developers.google.com/web/updates/2016/04/scroll-anchoring
-
@AtheistP3ace 这很可能是导致问题的原因。看起来我可以使用 overflow-anchor: none CSS 属性来解决问题。
-
甜蜜!很高兴你能弄清楚!祝你好运。
标签: javascript