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

iOS Safari中DOMContentLoaded失效,页面重载无法恢复滚动位置

iOS Safari表单提交后无法恢复滚动位置的问题修复

问题背景

页面重载(如表单提交后)需要保存并恢复当前滚动位置,现有代码在Chrome、Firefox及Android端浏览器正常生效,但在iOS Safari中无效。已针对DOMContentLoaded事件提前触发的问题做了修复,部署后问题仍存在。

原代码如下:

<script>
  function afterDOMLoaded() {
    var scrollpos = sessionStorage.getItem('scrollpos');
    if (scrollpos) {
        window.scrollTo(0, scrollpos);
        sessionStorage.removeItem('scrollpos');
    }
    
    window.addEventListener("beforeunload", function (e) {
      sessionStorage.setItem('scrollpos', window.scrollY);
    });
  }
  
  if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded',afterDOMLoaded);
  } else {
      afterDOMLoaded();
  }
</script>

失效原因

  1. beforeunload触发时机异常:iOS Safari在表单提交时,beforeunload事件触发时页面已开始卸载,window.scrollY可能已被重置为0,导致保存的滚动位置错误。
  2. sessionStorage读取延迟:DOMContentLoaded触发时,Safari可能还未完成sessionStorage的读取操作,导致无法获取到之前保存的滚动位置。
  3. 默认滚动恢复机制冲突:iOS Safari自带页面重载后自动恢复滚动位置的功能,会覆盖自定义的滚动恢复逻辑。

修复方案

1. 替换beforeunload为表单submit事件监听

针对表单提交场景,直接在表单提交时保存滚动位置,避免beforeunload的时机问题:

function saveScrollPos() {
  sessionStorage.setItem('scrollpos', window.scrollY);
}

// DOM加载完成后给所有表单绑定提交事件
document.addEventListener('DOMContentLoaded', function() {
  document.querySelectorAll('form').forEach(form => {
    form.addEventListener('submit', saveScrollPos);
  });
});

2. 延迟执行滚动恢复逻辑

给scrollTo添加微小延迟,确保sessionStorage读取完成,同时避开Safari的默认滚动时机:

function afterDOMLoaded() {
  var scrollpos = sessionStorage.getItem('scrollpos');
  if (scrollpos) {
    setTimeout(() => {
      window.scrollTo(0, parseInt(scrollpos));
      sessionStorage.removeItem('scrollpos');
    }, 100);
  }
}

3. 禁用浏览器默认滚动恢复

关闭Safari自带的滚动恢复功能,避免与自定义逻辑冲突:

if ('scrollRestoration' in history) {
  history.scrollRestoration = 'manual';
}

完整修复代码

<script>
  // 禁用浏览器默认滚动恢复
  if ('scrollRestoration' in history) {
    history.scrollRestoration = 'manual';
  }

  function saveScrollPos() {
    sessionStorage.setItem('scrollpos', window.scrollY);
  }

  function afterDOMLoaded() {
    var scrollpos = sessionStorage.getItem('scrollpos');
    if (scrollpos) {
      setTimeout(() => {
        window.scrollTo(0, parseInt(scrollpos));
        sessionStorage.removeItem('scrollpos');
      }, 100);
    }
    
    // 绑定所有表单的提交事件
    document.querySelectorAll('form').forEach(form => {
      form.addEventListener('submit', saveScrollPos);
    });
  }
  
  if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', afterDOMLoaded);
  } else {
    afterDOMLoaded();
  }
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:42:46