这篇文章发布于 2018年07月5日,星期四,01:42,归类于 Mobile相关。 阅读 35986 次, 今日 4 次 15 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=7765
本文可全文或部分转载,但需要保留原作者和出处。
一、mousemove报treated as passive错误
其实这个问题出现有一段时间了,主要麻烦的是,以前没有,后来,Chrome和Safari浏览器升级了,然后出现这个错误,而且就在一个月前,Chrome浏览器还只是黄色的警告,现在直接就红色错误献上。
例如,随便新建一个空白页面,写上如下JavaScript代码:
document.addEventListener('touchmove', function (event) { event.preventDefault(); });
然后在移动端模式下页面上点击滑来滑去记下,就可以看到一大堆错误:
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See…
红灿灿的报错截图如下:
这是因为Chrome及其内核浏览器更新了一项新特性,具体见(打开看人品):https://www.chromestatus.com/features/5093566007214080
如果仅仅是错误,不影响功能其实还好,但是,这个报错会影响我们之前运行很OK的交互操作,例如,自定义滚动,或者元素拖拽效果等,会触发浏览器原生的滚动,产生不好的交互体验效果。
如何解决这个问题呢?
我所知道的有两个方法。
二、方法一:touch-action:none解决passive错误
加入如下CSS:
html { touch-action: none; }
报错就会无影无踪。
补充于2021-12-08
touch-action:none
还可以用在使用 pointermove
事件实现拖拽或者拖移的场景,不然会没有效果。
——————
touch-action
是移动端一个与手势触摸密切相关的CSS属性,原本源自windows phone手机,微软系,后来被Chrome吸收借鉴,Firefox浏览器跟上,然后Safari也部分支持,目前已经可以说是在移动端可以畅行的CSS属性。
支持的关键字值有:
touch-action: auto; touch-action: none; touch-action: pan-x; touch-action: pan-left; touch-action: pan-right; touch-action: pan-y; touch-action: pan-up; touch-action: pan-down; touch-action: pinch-zoom; touch-action: manipulation;
其中:
auto
是默认值,表示手势操作什么的完全有浏览器自己决定(如<meta>元素的
)。viewport
设置manipulation
表示浏览器只允许进行滚动和持续缩放操作,类似双击缩放这种非标准操作就不可以。想当初,click
事件在移动端有个300ms
延时,就是因为避免和手机双击行为发生冲突。然而,当我们设置了touch-action:manipulation
干掉了双击行为,则显然,300ms
延时就不复存在,因此,下面的CSS声明可以用来避免浏览器300ms
延时问题。html { touch-action: manipulation; }
上面2个关键字属性值(auto
和manipulation
)是Safari唯一支持的两个touch-action
属性值,iOS Safari就是为用户操碎了心,就怕开发者把一些对用户无障碍访问有帮助的东西去掉,例如不支持touch-action:none
以及iOS10+中设置viewport
的user-scalable=no
已经无法阻止用户手指缩放屏幕了,或许在Safari看来,对于一个网页,没有任何理由阻止用户放大看你的网页内容。
至于其他关键字,正如字面意思,要么只能左移,要么只能左右移动,要么只能右移之类,具体如下:
none
表示不进行任何touch相关默认行为,例如,你想用手指滚动网页就不行,双击放大缩小页面也不可以,所有这些行为要自定义。pan-x
表示手指头可以水平移来移去。pan-left
表示手指头可以往左移动,移动开始后还是可以往右恢复的。pan-right
表示手指头可以可以往右移动,移动开始后还是可以往左恢复的。pan-y
表示手指头可以垂直移来移去。pan-up
表示手指头可以往上移,移动开始后还是可以往下恢复的。pan-down
表示手指头可以往下移,移动开始后还是可以往上恢复的。pan-zoom
表示手指头可以用来缩放页面。
上述部分关键字可以组合使用,分pan-y
, pan-up
, pan-down
和pan-x
, pan-left
, pan-right
以及pan-zoom
这三组,然后这三组关键字可以任意组合,例如:
.example { touch-action: pan-left pan-up pan-zoom; }
表示可以左移,上移和缩放。
此方法不足
1. iOS Safari浏览器不支持;
2. 干掉了可能需要的原生的touch相关行为。
不过主要问题还是iOS Safari浏览器不支持,第2点不足我们可以当我们需要阻止时候JS设置touch-action
为none
,不需要在JS还原即可,不是大问题。
iOS Safari对于传统移动网页可以重要浏览器,不可忽略,怎么办,有没有什么其他方法呢?有!就是下面这个。
三、方法二:passive:false解决passive错误
问题代码是:
document.addEventListener('touchmove', function (event) { event.preventDefault(); });
修复后的JavaScript代码是:
document.addEventListener('touchmove', function (event) { event.preventDefault(); }, { passive: false });
也就是addEventListener
的第三个参数传递passive:false
,告诉浏览器,我这个事件就是不是消极的,是老子主动要这么做的。浏览器此时也不好说什么,然后,我们以前出问题的代码就能正常运行了。
如果是Zepto.js语法下的事件呢,例如:
$(document).on('touchmove', function (event) { event.preventDefault(); });
根据我查看Zepto的源码分析,目前并不支持,请使用原生的addEventListener
代替。
四、结束语
意外学到了CSS touch-action
相关的一些知识。有了touch-action:manipulation
,我们可以在网页中放心大胆使用click
事件了,至于自定义的touch事件之流可以退出历史舞台了,哦也!
希望本文内容可以解决你遇到的问题,如果有其他方法,也欢迎不吝赐教。
最后,抛出一个我一直没解决的问题,在iOS Safari浏览器下,网页左右边缘滑动会自动跳到前一个或后一个浏览的网页,有没有什么办法可以阻止?
以上,感谢阅读!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=7765
(本篇完)
- mobilebone.js-mobile移动web APP单页切换骨架 (0.281)
- 移动端双指缩放图片JS事件的实践心得 (0.281)
- 细说iOS Safari下focus的行为 (0.217)
- PhoneGap/Cordova控制iOS7状态栏的显隐/颜色 (0.187)
- IE6下png背景不透明问题的综合拓展 (0.141)
- jQuery powerFloat万能浮动层下拉层插件 (0.141)
- 小tip: 微博新版查看大图前后浏览的另外一种实现 (0.141)
- 翻译-IE7/8@font-face嵌入字体与文字平滑 (0.080)
- CSS float浮动的深入研究、详解及拓展(二) (0.080)
- 对overflow与zoom"清除浮动"的一些认识 (0.080)
- 翻译 - CSS高峰会议内容精选 (RANDOM - 0.030)
ios 13 后全部支持啦
https://caniuse.com/?search=touch-action
“在iOS Safari浏览器下,网页左右边缘滑动会自动跳到前一个或后一个浏览的网页,有没有什么办法可以阻止”
body {
overscroll-behavior-x: none
}
这样吗
根据某些资料显示,iOS新的系统会提供解决方法。
“在iOS Safari浏览器下,网页左右边缘滑动会自动跳到前一个或后一个浏览的网页,有没有什么办法可以阻止?”
这个好像加上阻止冒泡的语句可以,不过不是很确定
所以有了 touch-action: manipulation; 就不需要用fastclick这种库来解决移动端300ms延迟了吗
这玩意儿貌似是避免混淆不同时长、类型的事件,造成判定过久而搞出来的一个暂缓之策,passive 就是告诉浏览器“没事你xjb搞吧我这肯定是按照 touchmove 来处理的不会出啥幺蛾子”,所以才不能`preventDefault()`
(去看迷渡的博客,有更详细的资源
没玩过手机端app,留个印象吧~~
在处理函数里 return false; 似乎也能解决这个问题,与上面的方法有关系么?
on(events,[selector],[data],fn)
events:一个或多个用空格分隔的事件类型和可选的命名空间,
selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代.
data:当一个事件被触发时要传递event.data给事件处理函数。
fn:该事件被触发时执行的函数。 false 值也可以做一个函数的简写,返回false。
这里面的 fn可以传
function(){
passive: false
}
解决treated as passive错误吗?
前两天遇到这个报错,使用方法一解决后,安卓机不能滑动了
我是使用方法二了后,安卓机和苹果机都不能滑动
用了方法一和方法二后,安卓机和苹果机下原生的滚动条都不能滑动
之前在触摸展屏上遇到了这个问题。
偷懒,换了火狐了事。
这次学习了。
赞.正好刚发现用的阿里的播放器也发生了这个问题.
这个问题之前困扰了我好久,谢谢大帅哥的博文!