填坑小能手——滚动嵌套

前言

前两天开心地摸着鱼,现场项目就提出了与滚动嵌入相关的问题:子元素滚动条滚动时外层滚动条滚动了,让修改为外层不滚动。卑微打工人只能乖乖去解决,下面来看下解决过程。

问题

为了研究现场问题,我们先写一个滚动嵌套的demo,看下滚动嵌套具体的行为。

根据图上的行为我们可以得出,子元素滚动条不到边缘时不会影响父元素滚动条,当滚动条到边缘时才会影响父元素。有没有什么办法取消影响呢?网上搜索下,发现了overscroll-behavior 属性。 overscroll-behavio可以控制滚动条滚动到边界的表现。该属性有三个值:

  • auto:默认值,具体表现就是图中所示。
  • contain:临近滚动区域不会被影响。
  • none:临近滚动区域不受影响并且阻止滚动到边界的行为。
    所以只要将overscroll-behavior的值设置为后两个就能解决我们的问题。添加overscroll-behavior属性后在页面尝试滚动,当子元素滚动跳触底后再次滚动父元素滚动条不动。接下来去项目中找到子元素添加overscroll-behavior属性就可以了。

解决

当我信心满满去找相关代码时,发现子元素的滚动条是用BS写的,滚动条表现跟上述分析的也不一样,只要子元素滚动外部滚动条就会滚动。叹口气决定死马当活马医,给子元素添加overscroll-behavior属性,结果并不生效,只好从BS入手。 BS是专门做滚动的库,支持各种各样与滚动相关的功能,公司项目是pc端,只是简单用到了鼠标滚轮与滚动条功能:

又观察了几次项目bug行为,发现BS包裹的元素滚动跟外层是同时进行的,有点像冒泡事件,子元素的滚动行为冒泡导致父元素也进行了滚动,感觉可以从元素事件入手。照着这个思路,检查了配置项又查阅BS官方文档发现了preventDefault属性,该属性用来阻止浏览器事件派发后的默认行为,默认为true,而配置项设置了false,浏览器行为都放开了,所以BS的滚动事件触发了浏览器的滚动行为。那么我们把preventDefault去掉就能解决问题,设置好再次尝试发现BS滚动条滚动并没有影响外层滚动条滚动。 虽然解决了滚动问题,但是引入了新问题,本身设置preventDefault为false就是不让阻止默认事件,跟之前的需求冲突了。幸好BS也考虑到了这个问题,定义了两个与之相关的属性:

  • preventDefaultException:后面跟正则表达式,匹配到的元素不会被阻止默认事件。
  • tagException:也是跟正则表达式,匹配到的元素不会影响BS滚动。
    刚开始我用了preventDefaultException发现不生效,后面用了tagException完美解决,官方文档上没有明确tagException此功能,果然还是得看实际操作啊。

总结

以上就是滚动嵌套问题的解决,解决过程中认识到了overscroll-behavior属性,顺带加深了对BS的认知,大家如果碰到类似问题,可以从以上两方法考虑,一个样式;一个事件。

相关推荐
盛夏绽放6 小时前
jQuery 知识点复习总览
前端·javascript·jquery
胡gh8 小时前
依旧性能优化,如何在浅比较上做文章,memo 满天飞,谁在裸奔?
前端·react.js·面试
大怪v9 小时前
超赞👍!优秀前端佬的电子布洛芬技术网站!
前端·javascript·vue.js
胡gh9 小时前
你一般用哪些状态管理库?别担心,Zustand和Redux就能说个10分钟
前端·面试·node.js
老华带你飞10 小时前
校园交友|基于SprinBoot+vue的校园交友网站(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·校园交友网站
roamingcode10 小时前
Claude Code NPM 包发布命令
前端·npm·node.js·claude·自定义指令·claude code
码哥DFS10 小时前
NPM模块化总结
前端·javascript
灵感__idea11 小时前
JavaScript高级程序设计(第5版):代码整洁之道
前端·javascript·程序员
唐璜Taro11 小时前
electron进程间通信-IPC通信注册机制
前端·javascript·electron
陪我一起学编程12 小时前
创建Vue项目的不同方式及项目规范化配置
前端·javascript·vue.js·git·elementui·axios·企业规范