为什么touchstart事件在移动端触发后无法阻止默认行为? W″翌喆 提问于 2026-02-07 15:18:25 阅读 34 移动 我在移动端开发时给按钮绑定了touchstart事件,想要阻止页面滑动的默认行为。代码是这样写的: element.addEventListener('touchstart', (e) => { e.preventDefault(); console.log('按钮被触摸'); }); 但测试时发现页面仍然可以滑动,明明调用了preventDefault(),这是哪里出问题了?其他事件比如click正常触发,但需要兼容触摸操作。 我来解答 赞 9 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 开发者艳青 Lv1 啊这,典型的移动端触摸事件坑点。关键点在于现代浏览器为了性能考虑,默认不会阻塞滚动,除非你把 touch-action CSS属性也设置上。 两种解决方案,选哪个看你需求: 1. 暴力但高效的方式,直接在CSS里干掉所有触摸滚动: .your-element { touch-action: none; } 2. 或者更精确控制,只在事件监听里处理。但要注意必须设置 passive: false 选项,不然preventDefault会被浏览器无视: element.addEventListener('touchstart', (e) => { e.preventDefault(); // 你的逻辑 }, { passive: false }); 为啥会这样?因为浏览器为了滚动性能优化,默认把touch事件设为passive。这帮搞浏览器引擎的家伙,为了60fps真是拼了... 我一般直接用第一种方案,效率更高,一劳永逸。除非你还要处理复杂手势才需要第二种。 回复 点赞 2026-03-06 18:05 Air-钰莹 Lv1 你这个问题挺常见的。在移动端,touchstart事件里直接调用e.preventDefault()确实看起来应该能阻止默认行为,比如页面滑动,但实际上系统对这个事件的处理机制比较特殊。 问题出在浏览器对触摸事件的默认处理流程上。touchstart触发时,浏览器还没有确定是滚动还是点击,所以即使你在touchstart里调用了preventDefault(),也不能保证能阻止整个滑动行为。 要真正阻止滑动,建议你换个思路:监听touchmove事件,而不是touchstart。你可以在这个事件里做判断,比如只有在手指按下后移动的时候才阻止默认行为: let isTouched = false; element.addEventListener('touchstart', () => { isTouched = true; }); element.addEventListener('touchmove', (e) => { if (isTouched) { e.preventDefault(); console.log('阻止滑动'); } }); element.addEventListener('touchend', () => { isTouched = false; }); 这样做的原理是,在touchstart里做一个标记,表示开始触摸,然后在touchmove中根据这个标记决定是否阻止默认行为。 另外,如果你只是想阻止某些特定区域的滑动,可以在touchmove事件中加一个判断,看事件目标是否在你关心的区域内,这样就不会影响页面其他部分的滚动体验。 还有一点要注意:iOS 上有些行为是系统级的,比如双指缩放和滑动返回等,这些用preventDefault()是拦不住的,得靠 CSS 的 touch-action 属性来控制更稳妥。 总之,别指望靠一个touchstart里的preventDefault()就能搞定所有,默认行为的拦截要做得更精细一点。 回复 点赞 4 2026-02-08 00:31 加载更多 相关推荐 2 回答 88 浏览 为什么我的Vue组件绑定的touchstart事件在移动端没反应? 我在用Vue开发移动端页面时,给按钮绑定了touchstart事件,但用手机测试完全没反应。换成click事件又能正常触发,这是为什么呢? 代码是这样写的: <template> <... 程序猿一茹 移动 2026-01-26 04:38:40 2 回答 36 浏览 为什么 touchstart 事件在 iOS 上没反应? 我在做一个移动端的滑动组件,用 touchstart 监听触摸开始,但在 iPhone 上完全没触发,安卓却正常。是不是哪里写错了? 我给元素加了下面这个 CSS,会不会是影响了事件冒泡? .slid... Mc.博泽 移动 2026-03-02 17:38:22 2 回答 43 浏览 为什么 touchstart 事件在 iOS 上有时不触发? 我在做一个移动端的滑动组件,用了 touchstart 监听手指按下,但在 iPhone 上经常点好几次才触发一次,安卓却正常。 试过给元素加 cursor: pointer 和 touch-acti... 夏侯世梅 移动 2026-02-27 11:14:20 2 回答 81 浏览 移动端触摸事件阻止冒泡后父元素点击还是触发了怎么办? 我在开发移动端列表滑动删除功能时遇到问题。子元素的touchstart事件里用了e.stopPropagation(),但父元素的点击事件还是会被触发,这是为什么呢? 具体场景是这样的:列表项有一个可... 雨欣酱~ 移动 2026-02-14 02:14:25 2 回答 236 浏览 React中touchend事件在移动端为什么没触发? 我在用React写移动端滑动删除功能时遇到问题,给元素绑定了touchstart和touchend事件,但结束触摸时事件没反应。手指离开屏幕后控制台只打印了touchstart,touchend完全没... 极客尚文 移动 2026-02-05 00:48:25 1 回答 18 浏览 为什么 touchmove 事件在移动端不触发? 我在做一个移动端的滑动组件,监听了 touchstart 和 touchmove,但发现 touchmove 根本没执行,控制台一点输出都没有。 试过给元素加 touch-action: none,也... 欧阳书圻 交互 2026-03-30 08:30:14 1 回答 42 浏览 移动端点击手势为什么经常误触发? 我在做一个移动端的卡片组件,想用 touchstart 和 touchend 来模拟点击事件,但经常轻轻滑动一下也会触发点击,体验很差。 试过用时间差和位移判断,但效果不稳定。比如下面这段逻辑: le... 开发者姿言 移动 2026-03-25 11:49:27 2 回答 106 浏览 Vue里怎么实现长按事件?touchstart和touchend老是不生效 我在移动端做了一个长按删除的功能,但用 touchstart 和 touchend 总是没反应,是不是我写法有问题? 试过加 passive: false 也没用,而且在真机上测试有时候会触发 cli... 百里乙豪 交互 2026-03-19 00:51:23 2 回答 73 浏览 为什么 touchmove 事件在移动端会触发多次甚至卡顿? 我在做一个滑动删除功能,监听了 touchstart 和 touchmove,但发现手指稍微一动就触发好多次 touchmove,而且页面还会卡一下。是不是我哪里写错了? 我试过用 e.prevent... Mr-玉英 移动 2026-03-17 22:19:18 1 回答 42 浏览 移动端手势滑动时 touchmove 事件不触发怎么办? 我在做一个移动端的滑动组件,监听了 touchstart 和 touchmove 事件,但发现有时候手指滑动了,touchmove 根本没触发,只触发了 touchstart 和 touchend。我... 设计师楚萓 交互 2026-03-15 05:55:20
touch-actionCSS属性也设置上。两种解决方案,选哪个看你需求:
1. 暴力但高效的方式,直接在CSS里干掉所有触摸滚动:
2. 或者更精确控制,只在事件监听里处理。但要注意必须设置
passive: false选项,不然preventDefault会被浏览器无视:为啥会这样?因为浏览器为了滚动性能优化,默认把touch事件设为passive。这帮搞浏览器引擎的家伙,为了60fps真是拼了...
我一般直接用第一种方案,效率更高,一劳永逸。除非你还要处理复杂手势才需要第二种。
touchstart事件里直接调用e.preventDefault()确实看起来应该能阻止默认行为,比如页面滑动,但实际上系统对这个事件的处理机制比较特殊。问题出在浏览器对触摸事件的默认处理流程上。
touchstart触发时,浏览器还没有确定是滚动还是点击,所以即使你在touchstart里调用了preventDefault(),也不能保证能阻止整个滑动行为。要真正阻止滑动,建议你换个思路:监听
touchmove事件,而不是touchstart。你可以在这个事件里做判断,比如只有在手指按下后移动的时候才阻止默认行为:这样做的原理是,在
touchstart里做一个标记,表示开始触摸,然后在touchmove中根据这个标记决定是否阻止默认行为。另外,如果你只是想阻止某些特定区域的滑动,可以在
touchmove事件中加一个判断,看事件目标是否在你关心的区域内,这样就不会影响页面其他部分的滚动体验。还有一点要注意:iOS 上有些行为是系统级的,比如双指缩放和滑动返回等,这些用
preventDefault()是拦不住的,得靠 CSS 的touch-action属性来控制更稳妥。总之,别指望靠一个
touchstart里的preventDefault()就能搞定所有,默认行为的拦截要做得更精细一点。