记录一下使用vue.js封装锚点组件的代码。项目中存在固定头部的情况。
主要思路为在组件初始化时,将锚点列表中的位置一次性获取,在点击锚点时,直接使用document.documentElement.scrollTop进行定位。添加页面滑动事件,在页面滑动时判断当前页面展示部分属于哪个锚点,动态渲染锚点高亮。
完整组件地址:传送门
// 分步滑动页面进行定位
byStepShow: function(scrollTop) {
let top = Math.abs(document.documentElement.scrollTop - scrollTop)
const $this = this
const animationCallback = function() {
top -= $this.stepHeight
if (top <= 0) {
document.documentElement.scrollTop = scrollTop
return
} else {
requestAnimationFrame(animationCallback)
if (document.documentElement.scrollTop > scrollTop) {
document.documentElement.scrollTop = document.documentElement.scrollTop - top
} else {
document.documentElement.scrollTop = document.documentElement.scrollTop + top
}
}
}
animationCallback()
},
// 滚动页面时的监听回调函数
onScroll: function() {
if (this.anchorList.length === 0) {
return
}
if (this.anchorPosition.length === 0 || this.scrollAlwaysComputePosition) {
this.anchorList.forEach(anchor => {
const toElement = document.querySelector('#' + anchor.id)
if (toElement) {
this.anchorPosition.push({
id: anchor.id,
position: toElement.offsetTop + (this.fixedHeader ? -this.headerHeight : this.headerHeight)
})
}
})
}
// 因为页面头部信息是固定高度的,需要在浏览器滚动条滚动页面时,加上头部高度计算定位位置
const headerHeight = this.fixedHeader ? -this.headerHeight : this.headerHeight
let scrolled = document.documentElement.scrollTop || document.body.scrollTop
scrolled = Math.ceil(headerHeight + scrolled)
// 将锚点位置列表根据锚点位置排序
this.anchorPosition.sort(function(pre, next) { return pre.position - next.position })
// 根据页面位置进行当前锚点高亮
for (let i = 0; i < this.anchorPosition.length - 1; i++) {
if (scrolled >= this.anchorPosition[i].position && scrolled < this.anchorPosition[i + 1].position) {
this.activeAnchor = this.anchorPosition[i].id
}
}
if (this.anchorPosition.length === 0) {
return
}
if (scrolled >= this.anchorPosition[this.anchorPosition.length - 1].position) {
this.activeAnchor = this.anchorPosition[this.anchorPosition.length - 1].id
}
}