VueJS 如何禁用外层div滚动 待内层div滚动到底部后恢复外层滚动
实现思路
- 监听外层滚动容器的
scroll事件,判断第一个区块是否完全滚动到视口外:核心逻辑为外层容器scrollTop + 视口高度 >= 第一个区块高度,可设置1~2px的阈值避免浏览器精度问题导致判断失效 - 触发条件后给外层容器设置
overflow: hidden禁用外层滚动,同时给第二个div设置overflow-y: auto启用内层滚动 - 监听第二个div的
scroll事件,判断是否滚动到内层底部,触底后恢复外层容器的overflow-y: auto即可恢复外层滚动能力 - 滚动事件添加防抖处理,避免频繁触发导致的性能损耗,也可减少边界条件下的反复触发问题
完整代码示例
<div class="outer-container"> <div class="section section-1">第一个区块内容</div> <div class="section section-2">第二个区块内容</div> <div class="section section-3">后续其他区块内容</div> </div>
* { margin: 0; padding: 0; box-sizing: border-box; } .outer-container { width: 100vw; height: 100vh; overflow-y: auto; scroll-behavior: smooth; } .section { width: 100%; height: 100vh; } .section-1 { background: #f5f5f5; padding: 24px; font-size: 20px; } .section-2 { background: #e0f7fa; overflow-y: hidden; /* 默认关闭内层滚动 */ padding: 24px; font-size: 18px; line-height: 2; } .section-3 { background: #f3e5f5; padding: 24px; font-size: 20px; }
const outer = document.querySelector('.outer-container') const section1 = document.querySelector('.section-1') const section2 = document.querySelector('.section-2') const section1Height = section1.offsetHeight // 防抖函数 function debounce(func, delay = 10) { let timer = null return function(...args) { clearTimeout(timer) timer = setTimeout(() => func.apply(this, args), delay) } } // 判断元素是否滚动到底部 function isScrollBottom(el, offset = 2) { return el.scrollTop + el.clientHeight >= el.scrollHeight - offset } // 外层滚动监听 const outerScrollHandler = debounce(() => { if (outer.scrollTop + outer.clientHeight >= section1Height) { // 第一个区块完全滚出视口,禁用外层滚动,启用内层滚动 outer.style.overflowY = 'hidden' section2.style.overflowY = 'auto' } }) outer.addEventListener('scroll', outerScrollHandler) // 内层滚动监听 const innerScrollHandler = debounce(() => { if (isScrollBottom(section2)) { // 内层滚动到底部,恢复外层滚动 outer.style.overflowY = 'auto' section2.style.overflowY = 'hidden' outer.scrollTop = section1Height + 1 // 避免停在边界反复触发 } }) section2.addEventListener('scroll', innerScrollHandler) // 测试用:填充第二个区块的内容 for(let i = 0; i < 100; i++) { section2.innerHTML += `<p>第二个区块第${i+1}行测试内容</p>` }
适配拓展说明
- 如需支持反向滚动(用户在内层向上滚动回到顶部时切回外层滚动),可在内层滚动监听中增加判断:当
section2.scrollTop === 0时,恢复外层滚动、禁用内层滚动即可 - 移动端适配可额外监听
touchmove事件处理,避免出现滚动穿透问题 - 多组嵌套滚动场景可将上述逻辑封装为通用函数,传入对应容器节点即可复用
内容的提问来源于stack exchange,提问作者Jet Lye
相关产品推荐
相关产品推荐

