如何在页面滚动至底部80%时禁止向下滚动且兼容iPhone设备?
兼容iOS的滚动限制实现方案
原有代码iOS失效原因
原有代码存在两个核心问题导致iOS设备不生效且功能不符合要求:
- iOS Safari 11.3之后默认将
touchmove、scroll事件设为passive模式,该模式下e.preventDefault()会被系统直接忽略,必须显式声明passive: false才能正常触发阻止行为 - 代码直接阻止了所有触摸事件,没有区分滚动方向,会导致向上滚动也被禁用
核心实现逻辑
首先计算页面滚动进度,当页面滚动高度 + 视口高度 >= 文档总高度 * 0.8时判定到达阈值,此时仅阻止向下滚动行为,允许用户向上滚动。
原生JS(React)完整实现
useEffect(() => { // 滚动阈值:滚动至文档总高度的80%时触发限制 const SCROLL_THRESHOLD = 0.8 // 记录上一次滚动的Y轴坐标,用于判断滚动方向 let lastYPosition = window.scrollY // PC端滚动事件处理 const handleScroll = (e) => { const currentScrollTop = window.scrollY const viewportHeight = window.innerHeight const docFullHeight = document.documentElement.scrollHeight const isReachThreshold = (currentScrollTop + viewportHeight) >= docFullHeight * SCROLL_THRESHOLD // 方向判断:当前滚动高度大于上一次即为向下滚动 const isScrollDown = currentScrollTop > lastYPosition if (isReachThreshold && isScrollDown) { e.preventDefault() return } lastYPosition = currentScrollTop } // 移动端touch事件处理,兼容iOS const handleTouchMove = (e) => { const currentTouchY = e.touches[0].clientY const currentScrollTop = window.scrollY const viewportHeight = window.innerHeight const docFullHeight = document.documentElement.scrollHeight const isReachThreshold = (currentScrollTop + viewportHeight) >= docFullHeight * SCROLL_THRESHOLD // 触摸场景方向判断:手指y坐标小于上一次即为向上滑,对应页面向下滚动 const isScrollDown = currentTouchY < lastYPosition if (isReachThreshold && isScrollDown) { e.preventDefault() } lastYPosition = currentTouchY } // 绑定事件,显式声明passive: false兼容iOS window.addEventListener('scroll', handleScroll, { passive: false }) window.addEventListener('touchmove', handleTouchMove, { passive: false }) // 组件卸载时移除事件监听,避免内存泄漏 return () => { window.removeEventListener('scroll', handleScroll) window.removeEventListener('touchmove', handleTouchMove) } }, [])
注意:建议给滚动事件添加节流处理,避免频繁触发导致性能损耗。
纯CSS备选方案
如果是固定容器滚动场景,不需要动态计算阈值,可以直接用CSS实现,无兼容性问题:
/* 给滚动容器添加以下样式 */ .scroll-box { /* 限制容器最大可滚动高度为视口的80% */ max-height: calc(100vh * 0.8); overflow-y: auto; /* 兼容iOS的弹性滚动效果 */ -webkit-overflow-scrolling: touch; }
常用工具包推荐
- 节流工具:
lodash.throttle,用于降低滚动事件触发频率,优化性能 - 钩子工具:
react-use库的useScroll钩子,可以直接获取滚动位置、滚动方向等参数,无需手动计算
内容的提问来源于stack exchange,提问作者アリ・ナディム
相关产品推荐
相关产品推荐

