今天正在愉快的敲代码的时候,测试突然给我发来一条消息!(测试发消息准没好事),果然,我的代码又双叒叕出bug了!
我看看怎么事?
事情是这样的,页面会根据URL上的hash值滚动到对应锚点位置,拿到hash之后获取到id=hash的a标签,然后计算出a标签的offsetTop,直接通过window.scrollTo(0, offsetTop)滚动到对应位置即可。
然后就有问题了,其他a标签都能跳过去,怎么其中一个就是滚动不了呢?通过打印它的offsetTop发现明显不对。
offsetTop 是一个只读属性,返回当前元素相对于 offsetParent 节点顶部边界的偏移像素值。
返回值包含:
- 元素顶部偏移的像素值,元素的外边距(margin)
- offsetParent 元素的顶部内边距(padding)、边框(border)及滚动条
注意: offsetParent 元素是一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的元素。
原来是offsetTop的问题,它不是直接获取到绝对位置,而是返回当前元素相对于 offsetParent 节点顶部边界的偏移像素值。
而我那个问题就是因为这个,a标签的父元素开启了定位,所以获取的值是当前元素相对于 offsetParent 节点顶部边界的偏移像素值,那按这个值滚动肯定是不准确的,通过以下方法改造,获取到了准确的值。
function getElementTop(element){
let actualTop = element.offsetTop;
let current = element.offsetParent;
while (current !== null){
actualTop += current.offsetTop;
current = current.offsetParent;
}
return actualTop;
}