背景
业务需求:富文本markdown表格区域需要支持双向滚动
-
水平滚动:查看表格更多列
-
垂直滚动:滚动整个页面内容
技术挑战:在分享弹窗环境中,表格的垂直滚动被"劫持",无法驱动页面滚动
解决方案:Touch 事件 + 鼠标滚轮精确控制
核心思路
通过 JavaScript 精确控制触摸事件和鼠标滚轮事件,区分滑动/滚动方向并分别处理:
-
垂直滑动/滚动:阻止表格默认行为,手动控制页面/弹窗滚动
-
水平滑动/滚动:让表格自然处理,实现列的水平滚动
支持的输入方式
-
移动端:触摸滑动手势
-
桌面端:鼠标滚轮滚动
实现步骤
1. 环境检测
首先检测当前是否在指定环境中,因为不同环境的滚动目标不同:
2. 事件监听
监听触摸事件和鼠标滚轮事件:
// 触摸开始:记录初始位置 // 触摸移动:方向判断和滚动控制 // 触摸结束:重置状态 // 鼠标滚轮事件:直接处理滚动
3. 滑动方向判断
这是方案的核心,通过计算滑动距离和设置合理阈值来准确判断用户意图:
4. 垂直滚动处理
触摸滑动处理:根据环境选择不同的滚动目标:
鼠标滚轮处理:相对简单,直接根据滚轮方向处理:
5. CSS 配置
.test { overflow-x: auto; // 允许水平滚动 overflow-y: hidden; // 禁用垂直滚动,完全由 JS 控制 overscroll-behavior-x: contain; // 水平滚动限制在表格内 overscroll-behavior-y: none; // 垂直滚动不产生边界效果 -webkit-overflow-scrolling: touch; // iOS 滚动优化 }
6. 事件监听器注册
在组件生命周期中正确注册和清理事件监听器:
// 组件挂载时注册 // 组件卸载时清理
关键技术点
1. 触摸事件的阈值设置
const SWIPE_THRESHOLD = 10 // 太小容易误触,太大响应迟钝 const DIRECTION_THRESHOLD = 30 // 确保方向判断的准确性
2. 滚动敏感度调整
// 触摸滑动:需要调整敏感度 const scrollSpeed = -deltaY * 0.8 // 0.8 是经过测试的最佳系数 // 鼠标滚轮:直接使用原始值 shareOverview.scrollTop += event.deltaY
3. 连续滚动支持
// 触摸滑动:更新起始位置 touchStartY = touch.clientY // 实现流畅的连续滚动 // 鼠标滚轮:天然支持连续滚动,无需特殊处理
4. 事件监听器配置
{ passive: false } // touchmove 和 wheel 需要能够 preventDefault { passive: true } // touchstart/touchend 可以被动监听,提升性能
5. 输入方式差异处理
方向判断 | 需要计算阈值 | 直接通过 deltaX/deltaY |
滚动距离 | 需要敏感度调整 | 直接使用 deltaY |
连续操作 | 需要更新起始位置 | 天然支持 |
性能考虑 | 高频触发,需要优化 | 相对低频 |
性能优化
-
最小化 DOM 查询:缓存常用的 DOM 元素引用
-
合理使用 preventDefault:只在必要时阻止默认行为
-
事件委托:在容器级别监听事件,减少监听器数量
-
节流处理:对于高频触发的滚动事件可以考虑节流
兼容性考虑
-
Touch Events:现代移动端浏览器支持良好
-
Wheel Events:现代桌面端浏览器支持良好
-
preventDefault:需要
passive: false
才能生效 -
scrollBy/scrollTop:标准 API,兼容性好
-
querySelector:现代浏览器标准支持
实际效果
实现后的效果:
移动端触摸:
-
✅ 分享弹窗中:表格区域上下滑动 → 弹窗页面滚动
-
✅ 单独使用时:表格区域上下滑动 → 页面滚动
-
✅ 两种环境:表格区域左右滑动 → 表格水平滚动
桌面端鼠标:
-
✅ 分享弹窗中:表格区域垂直滚轮 → 弹窗页面滚动
-
✅ 单独使用时:表格区域垂直滚轮 → 页面滚动
-
✅ 两种环境:表格区域水平滚轮 → 表格水平滚动
整体体验:
-
✅ 滚动体验流畅自然,无卡顿感
-
✅ 支持多种输入方式,适配不同设备
总结
Touch 事件 + 鼠标滚轮精确控制方案虽然代码相对复杂,但在复杂滚动场景中提供了:
-
完全的可控性:可以精确控制每种滚动行为
-
全平台支持:同时支持移动端和桌面端
-
良好的兼容性:基于标准的 Touch Events 和 Wheel Events API
-
灵活的扩展性:可以轻松适配不同的业务场景
在处理复杂滚动冲突问题时,JavaScript 精确控制往往比纯 CSS 方案更可靠,特别是需要同时支持多种输入方式的场景。