现象
用最新的 Chrome,或者是 Android 系统更新最新的 Android Webview,会遇到这个错误
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/509356600721
例如,随便新建一个空白页面,写上如下JavaScript代码:
document.addEventListener('touchmove', function (event) {
event.preventDefault();
});
然后在移动端模式下页面上点击滑来滑去记下,就可以看到上面的错误。
以前这个错误还只是黄色的警告(Chrome 56+)。
原因
这是因为Chrome及其内核浏览器更新了一项新特性,具体见(打开看人品):https://www.chromestatus.com/features/5093566007214080
如果仅仅是错误,不影响功能其实还好,但是,这个报错会影响我们之前运行很OK的交互操作,例如,自定义滚动,或者元素拖拽效果等,会触发浏览器原生的滚动,产生不好的交互体验效果。
解决办法
直接传递 passive:false
解决 treated as passive 错误
修复后的JavaScript代码是:
document.addEventListener('touchmove', function (event) {
event.preventDefault();
}, {
passive: false
});
也就是addEventListener的第三个参数传递 passive:false
,告诉浏览器,我这个事件就是不是消极的,是老子主动要这么做的。浏览器此时也不好说什么,然后,我们以前出问题的代码就能正常运行了。
Sencha Touch 和 ExtJS 6.0
Sencha Touch 和 ExtJS 6.0 是利用 css transform 模拟的滚动,其实类似的滚动 js 库有很多,比如 iscroll。
解决办法:
1、如果是 Sencha Touch,修改下面 2 个文件
MyApp\touch\src\viewport\Default.js
MyApp\touch\sencha-touch-all-debug.js
找到
applyPreventPanning: function(preventPanning) {
if (preventPanning) {
this.addWindowListener('touchmove', this.doPreventPanning, false);
}
else {
this.removeWindowListener('touchmove', this.doPreventPanning, false);
}
return preventPanning;
}
改为
applyPreventPanning: function(preventPanning) {
if (preventPanning) {
window.addEventListener('touchmove', this.doPreventPanning, { capture: false, passive: false });
}
else {
window.removeEventListener('touchmove', this.doPreventPanning, { capture: false, passive: false });
}
return preventPanning;
}
2、如果是 ExtJS 6.0,修改
MyApp\ext\modern\modern\src\viewport\Default.js
MyApp\ext\build\ext-modern-all-debug.js
找到
updatePreventPanning: function(preventPanning) {
this.toggleWindowListener(preventPanning, 'touchmove', this.doPreventPanning, false);
}
改为
updatePreventPanning: function(preventPanning) {
if (preventPanning) {
window.addEventListener('touchmove', this.doPreventPanning, { capture: false, passive: false });
} else {
window.removeEventListener('touchmove', this.doPreventPanning, { capture: false, passive: false });
}
}