填坑小能手——滚动嵌套

前言

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

问题

为了研究现场问题,我们先写一个滚动嵌套的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的认知,大家如果碰到类似问题,可以从以上两方法考虑,一个样式;一个事件。

相关推荐
自由与自然2 分钟前
栅格布局常用用法
开发语言·前端·javascript
Violet_YSWY10 分钟前
讲一下ruoyi-vue3的前端项目目录结构
前端·javascript·vue.js
这是你的玩具车吗10 分钟前
转型成为AI研发工程师之路
前端·ai编程
Drift_Dream13 分钟前
在Vue样式中使用JavaScript 变量(CSS 变量注入)
前端
C_心欲无痕13 分钟前
vue3 - toRaw获取响应式对象(如由reactive创建的)的原始对象
前端·javascript·vue.js
PlankBevelen13 分钟前
手搓实现简易版 Vue2 响应式系统
前端
LoveDreaMing15 分钟前
MCP入门梳理
前端·typescript·mcp
小林攻城狮16 分钟前
一个基于 canvas 的 pdf 图片分页切割方法
前端·javascript
老华带你飞18 分钟前
学生宿舍管理|基于java + vue学生宿舍管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
一天前19 分钟前
一个功能强大的 React Native 拖拽排序组件库,支持单列和多列布局,提供流畅的拖拽体验和自动滚动功能
前端