You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保留location.href逻辑同时不干扰自定义JS平滑滚动效果

问题原因

直接给location.href赋值带锚点hash的地址时,浏览器会原生触发瞬时跳转到对应锚点元素的默认行为,这个行为会立即中断后续window.scrollTo执行的平滑滚动过程,直接把页面定位到锚点位置,导致自定义平滑效果失效。


可行方案(无需删除URL更新逻辑、无需依赖CSS平滑滚动)

方案1:使用history.replaceState更新URL(推荐)

history.replaceState只会更新浏览器地址栏的URL显示,不会触发页面刷新、不会触发默认锚点滚动,完全不会干扰后续的自定义平滑滚动逻辑,同时能保留你需要的URL区块标识功能。
你只需要把原代码中给location.href赋值的部分替换掉即可,其余逻辑完全不用修改:

document.getElementById('link_no' + (i + 1)).classList.add('active-link');

// 替换原有的location.href赋值逻辑
// let currentLocation = location.href;
// currLocationArray = currentLocation.split("#");
// currentLocation = currLocationArray[0];
// currentLocation += `#section${i+1}`;
// location.href = currentLocation;
history.replaceState(null, '', `#section${i+1}`);

// 以下自定义滚动逻辑保持原样即可
let sectionOfI = document.getElementById(`section${i+1}`);
let scrollArea = getOffset(sectionOfI);
scrollEventNew(scrollArea.top,e);

这个方案的优势:

  • 地址栏正常展示#section1/#section2这类区块标识,支持用户复制链接分享、刷新页面定位
  • 无任何默认副作用,不会打断JS平滑滚动
  • 代码改动量极小,不需要调整现有滚动函数

方案2:临时移除锚点id(极端兼容场景兜底)

如果需要兼容不支持History API的极老旧浏览器,可以通过临时移除目标区块id的方式,让浏览器找不到对应锚点、无法触发默认跳转,等URL更新完成后再恢复id,最后执行自定义滚动:

document.getElementById('link_no' + (i + 1)).classList.add('active-link');
let sectionOfI = document.getElementById(`section${i+1}`);
// 临时暂存并移除目标区块的id
const originId = sectionOfI.id;
sectionOfI.removeAttribute('id');
// 更新URL的hash
location.hash = `#section${i+1}`;
// 立即恢复id
sectionOfI.id = originId;

// 执行自定义平滑滚动
let scrollArea = getOffset(sectionOfI);
scrollEventNew(scrollArea.top,e);

注意:不要直接使用location.hash = xxx的写法更新锚点,该写法和给location.href赋值带hash的地址效果一致,都会触发默认瞬时滚动,打断平滑效果。

内容的提问来源于stack exchange,提问作者srohome

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:48:39