移动端阻止默认事件

为了提高页面滚动流畅性,Chrome56开始默认将touchstart和touchmove事件设为passive:true,忽略preventDefault()以实现即时滚动。然而这可能导致一些问题,比如阻止默认行为失效等。本文介绍了两种解决方法:一是明确声明事件监听器为非被动的;二是使用CSS属性touch-action:none。

由于浏览器必须要在执行事件处理函数之后,才能知道有没有掉用过 preventDefault() ,这就导致了浏览器不能及时响应滚动,略有延迟。

所以为了让页面滚动的效果如丝般顺滑,从 chrome56 开始,在 window、document 和 body 上注册的 touchstart 和 touchmove 事件处理函数,会默认为是 passive: true。浏览器忽略 preventDefault() 就可以第一时间滚动了。

举例:
wnidow.addEventListener(‘touchmove’, func) 效果和下面一句一样
wnidow.addEventListener(‘touchmove’, func, { passive: true })
这就导致了一个问题:

如果在以上这 3 个元素的 touchstart 和 touchmove 事件处理函数中调用 e.preventDefault() ,会被浏览器忽略掉,并不会阻止默认行为。
测试:

body {
margin: 0;
height: 2000px;
background: linear-gradient(to bottom, red, green);
}

// 在 chrome56 中,照样滚动,而且控制台会有提示,blablabla
window.addEventListener(‘touchmove’, e => e.preventDefault())
那么如何解决这个问题呢?不让控制台提示,而且 preventDefault() 有效果呢?
两个方案:
1、注册处理函数时,用如下方式,明确声明为不是被动的
window.addEventListener(‘touchmove’, func, { passive: false })

2、应用 CSS 属性 touch-action: none; 这样任何触摸事件都不会产生默认行为,但是 touch 事件照样触发。
touch-action 还有很多选项,详细请参考touch-action

[注]未来可能所有的元素的 touchstart touchmove 事件处理函数都会默认为 passive: true

<think> 我们讨论的是在`pointerup`事件阻止默认事件的方法。根据引用[1],我们知道指针事件可以通过JavaScript或CSS来阻止默认行为。在`pointerup`事件中,我们可以使用`event.preventDefault()`来阻止默认行为。 但是,需要注意的是,不同的浏览器和场景下,阻止默认事件的效果可能不同。尤其是在移动端阻止默认事件可能会影响页面滚动等行为,所以要谨慎使用。 根据引用[3],指针事件是跨设备的(包括PC和移动端),因此处理方式相对统一。 ### 如何在`pointerup`事件阻止默认事件? 1. **添加事件监听器**:在目标元素上添加`pointerup`事件监听器。 2. **调用`preventDefault`方法**:在事件处理函数中,调用事件对象的`preventDefault()`方法。 代码示例: ```javascript element.addEventListener('pointerup', function(event) { // 阻止默认事件 event.preventDefault(); // 这里可以添加自定义逻辑 }); ``` ### 注意事项: - 如果需要在`pointerup`事件阻止默认行为,确保在事件传播的早期阶段(如捕获阶段)进行处理,因为某些默认行为可能在事件冒泡阶段之前就已经发生。 - 考虑使用`{ passive: false }`作为第三个参数,以确保`preventDefault()`可以正常工作(特别是在涉及滚动的场景中): ```javascript element.addEventListener('pointerup', function(event) { event.preventDefault(); // ... }, { passive: false }); // 确保可以阻止默认行为 ``` ### 为什么要设置`{ passive: false }`? 根据引用[1],当我们需要阻止默认行为时,必须将事件监听器设置为非被动模式(passive: false),因为被动模式下调用`preventDefault()`会被忽略。 ### 兼容性考虑: 指针事件在大多数现代浏览器中支持良好,但在一些旧浏览器中可能不支持。可以使用特性检测: ```javascript if (window.PointerEvent) { // 支持指针事件 element.addEventListener('pointerup', handler, { passive: false }); } else { // 不支持指针事件,可能需要回退到鼠标事件或触摸事件 } ``` ### 结合引用[4]的事件对象属性: 在事件处理函数中,我们可以利用事件对象的属性,例如: - `event.target`:获取事件目标 - `event.currentTarget`:获取当前处理事件的对象 - `event.isTrusted`:判断事件是否由用户交互触发 ### 示例:阻止链接的默认行为(跳转) 假设我们有一个链接,我们希望在`pointerup`事件阻止其跳转: ```html <a href="https://example.com" id="myLink">点击我</a> ``` ```javascript const link = document.getElementById('myLink'); link.addEventListener('pointerup', function(e) { e.preventDefault(); // 阻止跳转 console.log('阻止了跳转'); }, { passive: false }); ``` 注意:由于链接的默认行为通常由`click`事件触发,而`pointerup`事件在`click`之前触发,所以这里阻止`pointerup`的默认行为并不能直接阻止跳转(因为跳转是由`click`触发的)。因此,更合适的做法是在`click`事件阻止默认行为。但是,如果链接的默认行为与`pointerup`有关(例如,某些浏览器可能在`pointerup`时就开始导航),那么上述方法可能有效。不过,通常情况下,为了阻止链接跳转,我们更倾向于在`click`事件阻止。 ### 所以,如果我们确实需要在`pointerup`事件阻止默认行为,并且这个默认行为是独立于`click`的(例如,可能是浏览器在`pointerup`时触发的某些默认行为),那么上述方法是适用的。 ### 总结: 在`pointerup`事件阻止默认事件的方法就是在事件处理函数中调用`event.preventDefault()`,并确保事件监听器设置为非被动模式(`{ passive: false }`)。 --- §§相关问题§§ 1. 如何区分指针事件中的不同指针类型(如鼠标、触控、触笔)? 2. 在移动端,如何同时处理触摸事件和指针事件? 3. 如何避免阻止默认行为对页面滚动造成的影响? </think> ### 在 `pointerup` 事件阻止默认事件的方法 在指针事件 (`PointerEvent`) 中阻止默认行为,需使用 `event.preventDefault()` 方法。以下是具体实现方案: #### 核心实现代码 ```javascript element.addEventListener('pointerup', (event) => { // 阻止默认行为(如链接跳转/图片拖拽等) event.preventDefault(); // 可选:阻止事件冒泡 event.stopPropagation(); console.log("Pointerup 默认行为已阻止", event); }, { passive: false }); // 必须设置为非被动监听[^1] ``` #### 关键注意事项 1. **必须禁用被动监听模式** 通过 `{ passive: false }` 参数显式声明事件监听器可能调用 `preventDefault()`: ```javascript // 正确配置 addEventListener('pointerup', handler, { passive: false }); // 错误配置(preventDefault将失效) addEventListener('pointerup', handler); // 默认passive: true ``` 2. **兼容移动端特殊行为** 移动端需额外处理 `touch-action` CSS 属性: ```css .prevent-element { touch-action: none; /* 完全禁用浏览器默认触摸行为[^1] */ } ``` 3. **区分事件阶段** 根据引用[2]的事件流模型,应在合适阶段拦截: ```javascript // 捕获阶段处理(优先执行) element.addEventListener('pointerup', handler, true); // 清理阶段重置状态(引用[2]的事件清理阶段) element.addEventListener('pointercancel', () => { console.log("指针交互被中断"); }); ``` #### 完整示例:阻止图片拖拽 ```html <img src="photo.jpg" class="prevent-drag" alt="示例图片"> <script> document.querySelector('.prevent-drag').addEventListener('pointerup', (e) => { e.preventDefault(); console.log("图片拖拽行为已阻止"); // 替换为自定义交互逻辑(如弹出预览框) }, { passive: false }); </script> <style> .prevent-drag { touch-action: none; /* 禁用默认拖拽行为[^1] */ user-select: none; /* 禁止内容选择 */ } </style> ``` ### 实现原理说明 1. **事件触发顺序** 完整指针事件流:`pointerdown → pointermove → pointerup → pointercancel`[^3] 2. **阻止时机** `pointerup` 是手势完成的确认阶段,此时阻止默认行为可中断浏览器后续操作(如链接跳转) 3. **与触摸事件区别** | 特性 | 指针事件 | 触摸事件 | |---|---|----| | 跨设备支持 | ✅ (PC/移动) | ❌ (仅移动) | | 延迟触发 | ❌ (立即触发) | ❌ (立即触发) | | 事件类型 | 10+种 | 4种[^3] | > **关键点**:移动端需同时设置 `touch-action: none` 和 `event.preventDefault()` 才能完全禁用默认行为。根据引用[1],这可以阻止浏览器中断指针事件流(避免触发 `pointercancel`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值