向阻止滚动的“touchstart”事件添加了非被动事件侦听器

Posted

技术标签:

【中文标题】向阻止滚动的“touchstart”事件添加了非被动事件侦听器【英文标题】:Added non-passive event listener to a scroll-blocking 'touchstart' event 【发布时间】:2018-02-16 02:34:19 【问题描述】:

今天突然间,我开始在我们网站的每个页面上都看到这个

Added non-passive event listener to a scroll-blocking 'touchstart' event.
Consider marking event handler as 'passive' to make the page more responsive

而且它不仅仅是一次或两次......它就像成千上万的......

他们疯了。

阻止违规泛滥的唯一方法是注释掉这一行

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js" type="text/javascript"></script>

我阅读了其他关于此违规含义的帖子,但我真的看不出我在两个小时前和现在之间做了什么不同(我做了一个完整的回滚只是为了看看它是否有帮助)

这几乎就像有人在 jquery.min.js 中放了一个错误,但我严重怀疑这一点,因为这样每个人都会得到它。

有什么想法吗?我尝试了所有可以调试的东西,但我仍然不知道是什么原因造成的?!?

更新

我用&lt;button data-toggle="tooltip" title="text"&gt;&lt;/button&gt; 替换了所有&lt;button&gt;&lt;md-tooltip&gt;text&lt;/md-tooltip&gt;&lt;/button&gt;,这消除了所有违规行为的99%。

【问题讨论】:

您的旧版本仍然可以使用吗?因为这很可能是添加了这个的浏览器更新...... 嗯,好问题......我今天所做的只是将Speed Dial 2 - New tab 2.2.1 添加为 chrome 浏览器扩展(让您控制空白页面快捷方式) - 但我卸载了它以防万一造成问题。 尝试在 firefox 上运行页面,这里 jquery 在缩小代码的深处进入无限循环。 好的。尝试用未压缩的版本替换您的 jQuery 文件。查看错误时,您会有更好的想法。 【参考方案1】:

这解决了我的问题:

jQuery.event.special.touchstart = 
  setup: function( _, ns, handle )
    if ( ns.includes("noPreventDefault") ) 
      this.addEventListener("touchstart", handle,  passive: false );
     else 
      this.addEventListener("touchstart", handle,  passive: true );
    
  
;

【讨论】:

我应该在哪里添加这个?在 JS 中还是在 JS 后包含? 它对我有用,我只需要复制此代码即可抑制有关touchmove 的警告(只需将每个touchstart 替换为touchmove)。正如我从这个 jsbin (jsbin.com/bupesajoza/edit?html,js,output) 中了解到的,noPreventDefault 部分的目的是可以不使用“被动”侦听器。 if/else 块的内容应该交换:如果命名空间包含 noPreventDefault 那么被动应该有一个 default 值,即 真的 另一个注意事项是 IE11 不支持“includes()”。它导致了一个错误,阻止了所有产品页面在我们的网站上显示。您可以在此处找到有关 polyfill 或替代实现的更多信息:***.com/questions/31340868/… ie 11 兼容版本:jQuery.event.special.touchstart = setup: function( _, ns, handle ) if ((ns.indexOf('noPreventDefault') > -1)) this.addEventListener("touchstart", handle, passive: false ); else this.addEventListener("touchstart", handle, passive: true ); ;【参考方案2】:

我正在使用各种事件,这似乎解决了我的用例

(function () 
    if (typeof EventTarget !== "undefined") 
        let func = EventTarget.prototype.addEventListener;
        EventTarget.prototype.addEventListener = function (type, fn, capture) 
            this.func = func;
            if(typeof capture !== "boolean")
                capture = capture || ;
                capture.passive = false;
            
            this.func(type, fn, capture);
        ;
    ;
());

【讨论】:

好电话,这对我有用。我将此添加到我的 jQuery 文件的底部,称为 jquery.custom.min.js 并缩小它。像魅力一样工作。 在 Internet Explorer 中 EventTarget 似乎未定义。所以我建议在 var func =` 行之前添加if (typeof EventTarget !== 'undefined') 我更喜欢这个解决方案,但是我在控制台[Violation] Added synchronous DOM mutation listener to a 'DOMNodeRemoved' event. Consider using MutationObserver to make the page more responsive. 中遇到了这个错误,还没有弄清楚如何使用 Mutation Observers 重写它。请帮忙? 我在为 Google 地图标记设置动画时遇到了主题启动器的问题。此解决方案有效。【参考方案3】:

好吧,再挖掘一下,这不是一个新行为,前段时间已经报道过,jQuery 仍然没有修复它。

问题在于,对于要成为passive 的处理程序,它必须确定永远不会调用preventDefault(),但jQuery 事先并不知道...

我能给您的唯一提示是更改控制台日志记录级别并删除“详细”。关注this issue 以获得解决此问题的想法。

【讨论】:

问题是违规的数量会减慢网站的速度,我们在几个页面中 jQuery 进入无限循环并吐出多达 10,000 个违规(在我设法关闭浏览器之前)。如果我注释掉 jQuery,那么一切都很好。那么我们如何将处理程序设置为passive Ok Salketer - 发现了一些东西...&lt;md-tooltip&gt;testing&lt;/md-tooltip&gt; 是导致这种违规的一件事,因为我使用了很多这些我得到了很多错误。我仍在检查原因,我确定有移动的东西导致它。 还发现&lt;input type="date" ng-model="vm.date.checkin"&gt; 导致了很多这样的问题:[Violation] Added non-passive event listener to a scroll-blocking 'wheel' event. 但仅在您使用 ng-model 时才发生。 仅凭这些 sn-ps,我无法为您提供更多帮助。但基本上,所有导致滚动的事件(滚轮、触摸、滚动)都会抛出这个,因为 jQuery 事件处理可能会阻止它们。因此,请尝试在您的输入中删除该轮事件,这非常奇怪......并查看其他事件。您还可以通过使用事件委托来减少处理程序的数量。 现在我替换了所有 &lt;button&gt;&lt;md-tooltip&gt;text&lt;/md-tooltip&gt;&lt;/button&gt; 宽度 &lt;button data-toggle="tooltip" title="text"&gt;&lt;/button&gt; 这删除了 ​​99% 的违规行为。【参考方案4】:

Sergio 的回答是正确的,将它添加到底部的 jquery 脚本中。如果 touchstart 和 touchmove 有问题,只需添加相同的代码并将 touchstart 替换为 touchmove,如下所示:

jQuery.event.special.touchstart = 
  setup: function( _, ns, handle )
    if ( ns.includes("noPreventDefault") ) 
      this.addEventListener("touchstart", handle,  passive: false );
     else 
      this.addEventListener("touchstart", handle,  passive: true );
    
  
;
jQuery.event.special.touchmove = 
  setup: function( _, ns, handle )
    if ( ns.includes("noPreventDefault") ) 
      this.addEventListener("touchmove", handle,  passive: false );
     else 
      this.addEventListener("touchmove", handle,  passive: true );
    
  
;

【讨论】:

【参考方案5】:

我认为,除了基于触摸的事件之外,您还可以添加基于滚动的修复,以防止 google 页面得分将其标记为桌面与移动:

jQuery.event.special.wheel = 
    setup: function( _, ns, handle )
        this.addEventListener("wheel", handle,  passive: true );
    
;
jQuery.event.special.mousewheel = 
    setup: function( _, ns, handle )
        this.addEventListener("mousewheel", handle,  passive: true );
    
;

【讨论】:

以上是关于向阻止滚动的“touchstart”事件添加了非被动事件侦听器的主要内容,如果未能解决你的问题,请参考以下文章

h5 移动端在阻止touchstart的默认事件时报错

iPad - touchStart() 事件被 div 文本阻止

通过阻止 touchstart 事件,解决移动端的 BUG

警告:添加非被动事件侦听器到滚动阻塞'touchstart'事件(Added non-passive event listener to a scroll-blocking '

移动端事件

h5 slider页面滑动相关问题