我是在pc端 用swiper做了个整屏纵向滑动的效果,(用的框架是vue),虽然是个pc端项目,但是我想尽量的去适配移动端,为了方便期间,我把项目链接发送到了微信上,然后在微信里直接点击页面链接进去了,
这时,问题出现了,我发现当我用手指拖动页面时,会非常不好使,特别是切换到最底部的一屏时,简直无法往上拖动切换,我一拖动,整个页面就往下被拖动了,刚开始不知所措,然后上网查,结果查出了原因,
这是因为,在微信浏览器中,浏览器没能很好的分辨出我的拖动是拖动整个文档页面,还是拖动swiper里的slide使slide切换,
于是对症下药:我选择把body的touchmove事件去掉(所有的子元素的touchmove事件,冒泡到body后都会停止继续冒泡)
document.body.addEventListener('touchmove' , function(e){
e.preventDefault();
});
这太简单粗暴了,我自己又兼容了一下代码
document.body.addEventListener('touchmove' , function(e){
var e=e||window.event;
e.preventDefault();
},false)
在微信浏览器上试了一下,拖动已经好使了!!!!
正在兴奋之余,我的眼角余光票到了控制台,好像有一段红字哎????????报错了????(谷歌浏览器)
报错是:Unable to preventDefault inside passive event listener due to target being treated as passive.
有道词典翻译是这样的:无法防止被动事件侦听器内部的默认,因为目标被视为被动的
翻译了也不懂是哪里出错了,然后把报错代码贴到了度娘上,搜到答案了!!!!
大致意思是这样的:
由于浏览器必须要在执行事件处理函数之后,才能知道有没有掉用过 preventDefault() ,这就导致了浏览器不能及时响应滚动,略有延迟。
所以为了让页面滚动的效果如丝般顺滑,从 chrome56 开始,在 window、document 和 body 上注册的 touchstart 和 touchmove 事件处理函数,会默认为是 passive: true。浏览器忽略 preventDefault() 就可以第一时间滚动了。
举例:
wnidow.addEventListener('touchmove', func) 效果和下面一句一样
wnidow.addEventListener('touchmove', func, { passive: true })
以下是个人理解:
我想禁止掉touchmove事件,但是只能等到
touchmove事件触发之后,才会执行我的
preventDefault()。
由于现在谷歌浏览器默认
touchstart 和 touchmove 事件处理函数是被动的;也就是
{ passive: true }; passive:被动的
而现在我是调用了
touchmove事件之后才将他禁用的,所以会出现上面的报错,被动事件不能被阻止。
好了,报错原因找到了,那我将touchmove事件改成主动的不就行了嘛。。。。。。。
document.body.addEventListener('touchmove' , function(e){
var e=e||window.event;
e.preventDefault();
},
{ passive: false }
)报错消失了。。。
成功阻止微信拖动事件!!
网上还有解决办法:搬过来,占为己有
2、应用 CSS 属性 touch-action: none;
这样任何触摸事件都不会产生默认行为,但是 touch 事件照样触发。
touch-action 还有很多选项,详细请参考touch-action
[注]未来可能所有的元素的 touchstart touchmove 事件处理函数都会默认为 passive: true