考虑将事件处理程序标记为“被动”以使页面更具响应性

Posted

技术标签:

【中文标题】考虑将事件处理程序标记为“被动”以使页面更具响应性【英文标题】:Consider marking event handler as 'passive' to make the page more responsive 【发布时间】:2017-01-02 08:01:21 【问题描述】:

我正在使用锤子进行拖动,并且在加载其他内容时它变得不稳定,正如此警告消息所告诉我的那样。

“touchstart”输入事件的处理延迟了 X 毫秒,原因是 主线程忙。考虑将事件处理程序标记为“被动”以 使页面更具响应性。

所以我尝试像这样向听众添加“被动”

Hammer(element[0]).on("touchstart", function(ev) 
  // stuff
, 
  passive: true
);

但我仍然收到此警告。

【问题讨论】:

【参考方案1】:

对于第一次收到此警告的用户,这是由于最近(2016 年夏季)在浏览器中实施的称为被动事件侦听器 的前沿功能。来自https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md:

被动事件侦听器是 DOM 规范中的一项新功能,它启用 开发人员通过消除 需要滚动以阻止触摸和滚轮事件侦听器。 开发人员可以使用 passive: true 注释触摸和滚轮侦听器 表示他们永远不会调用 preventDefault。这项特征 在 Chrome 51、Firefox 49 中发布并登陆 WebKit。 For full official explanation read more here.

另见:What are passive event listeners?

您可能需要等待 .js 库实现支持。

如果您通过 javascript 库间接处理事件,您可能会受制于该特定库对该功能的支持。截至 2019 年 12 月,似乎没有任何主要库已实现支持。一些例子:

jQuery.js - 持续问题:https://github.com/jquery/jquery/issues/2871 React.js - 持续问题:https://github.com/facebook/react/issues/6436 Hammer.js - 由于没有跟进而关闭:https://github.com/hammerjs/hammer.js/pull/987 完美滚动条 - 关闭: https://github.com/noraesae/perfect-scrollbar/issues/560 AngularJS - 由于无法修复而关闭:https://github.com/angular/angular.js/issues/15901

【讨论】:

离子库怎么样? 我正在打电话给preventDefault() - 是否可以取消此警告? @maja no - ***.com/questions/44060131/… Google Maps JavaScript API 版本 3 也会生成这些警告。正在issuetracker.google.com/issues/63211698 跟踪问题。 (有点讽刺,考虑到 Google Chrome 会警告 Google Maps JavaScript API 生成的违规行为。) 要抑制这个警告,你可以` addEventListener('touchstart', this.callPassedFuntion, passive: false )`【参考方案2】:

这会隐藏警告消息:

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

【讨论】:

目标不是停止实际事件吗?在处理完问题之前,我不想隐藏消息。 我认为这是一个 jquery 库问题。我认为开发人员必须修复它。但如果你能得到它,请告诉我该怎么做。非常感谢。 当然是伊万!是的。嘿,现在我很好奇......我正在使用 d3 插件,我得到了 2300 次违规。也许您的代码会有所帮助!我会及时通知你的! @yardpenalty.com,不,停止活动不是目标!警告指出您已放置侦听器,但未指定它是否会阻止事件的默认行为。如果您有需要调用preventDefault() 的情况,则应指定passive: false。如果不是,请指定passive: true。如果您不指定任何一个,您只会收到警告。如果您指定passive: true 并调用preventDefault(),则会导致错误并且不会阻止默认设置。在这里指定passive 并不是一个技巧。这是解决方案。这就是警告所要求的! @tao 感谢您的评论。已经好几年了,但我一定会记住未来的解决方案!【参考方案3】:

以下库解决了该问题。 只需将此代码添加到您的项目中即可。

<script type="text/javascript" src="https://unpkg.com/default-passive-events"></script>

如果您需要更多信息,请访问此library。

【讨论】:

【参考方案4】:

对于那些遇到遗留问题的人,找到引发错误的行并添加passive: true - 例如:

this.element.addEventListener(t, e, !1)

变成

this.element.addEventListener(t, e,  passive: true )

【讨论】:

【参考方案5】:

对于带有 jquery-ui-touch-punch 的 jquery-ui-dragable,我修复了它类似于 Iván Rodríguez,但为 touchmove 增加了一个事件覆盖:

jQuery.event.special.touchstart = 
    setup: function( _, ns, handle ) 
        this.addEventListener('touchstart', handle,  passive: !ns.includes('noPreventDefault') );
    
;
jQuery.event.special.touchmove = 
    setup: function( _, ns, handle ) 
        this.addEventListener('touchmove', handle,  passive: !ns.includes('noPreventDefault') );
    
;

【讨论】:

【参考方案6】:

在 Laravel 的 select2 下拉插件中也会遇到这种情况。按照 Alfred Wallace 的建议从

更改值
this.element.addEventListener(t, e, !1)

this.element.addEventListener(t, e,  passive: true )

解决了这个问题。为什么他投了反对票,我不知道,但这对我有用。

【讨论】:

谢谢兄弟,这很好用 - 用 JQuery 3.5.1 测试 你为什么只是复制/粘贴另一个答案??【参考方案7】:

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

// 被动事件监听器(设置标志的两个细微差别)

jQuery.event.special.touchstart = 
    setup: function( _, ns, handle ) 
        this.addEventListener("touchstart", handle,  passive: !ns.includes("noPreventDefault") );
    
;
jQuery.event.special.touchmove = 
    setup: function( _, ns, handle ) 
        this.addEventListener("touchmove", handle,  passive: !ns.includes("noPreventDefault") );
    
;
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 );
    
;

【讨论】:

【参考方案8】:

我找到了一个适用于jQuery 3.4.1 slim的解决方案

解压缩后,在第 1567 行的 addEventListener 函数中添加 passive: true,如下所示:

t.addEventListener(p, a, passive: true))

没有任何问题,灯塔审计不会抱怨听众。

【讨论】:

永远不要更改库的源代码;你应该改写它。 如何在jquery中实现对事件监听器的覆盖? 对,绝对同意不改库……就说解决办法

以上是关于考虑将事件处理程序标记为“被动”以使页面更具响应性的主要内容,如果未能解决你的问题,请参考以下文章

信号处理程序与事件处理程序

不使用被动侦听器来提高滚动性能(灯塔报告)

添加 SVG 元素并使其具有响应性

如何让我的 CSS @media 代码在移动设备上运行以使我的网站具有响应性?

响应式设计 Xcode 6 - 如何设置约束以使您的设计响应式?

D3 Chart SVG响应条和轴