考虑将事件处理程序标记为“被动”的,以使页面更加响应。

280

我正在使用锤子进行拖动,当加载其他内容时变得卡顿,就像这个警告消息所告诉我的。

由于主线程繁忙,'touchstart'输入事件的处理被延迟了X毫秒。考虑将事件处理程序标记为'passive'以使页面更具响应性。

因此,我尝试在监听器中添加'passive',如下所示:

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

但我仍然收到这个警告。

9个回答

308

如果您第一次收到此警告,那是由于一个名为被动事件监听器的前沿功能在浏览器中最近实现(2016年夏季)。参考来自https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

被动事件监听器是DOM规范中的一个新功能,它使开发人员能够通过消除滚动对触摸和滚轮事件监听器的阻塞来选择更好的滚动性能。开发人员可以使用{passive: true}注释触摸和滚轮监听器,以指示它们永远不会调用preventDefault。该功能于Chrome 51、Firefox 49中推出,并已实现在WebKit中。要获取完整的官方解释,请在此处阅读更多内容。

另请参见:什么是被动事件监听器?

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

如果您间接地通过JavaScript库处理事件,可能要看这个特定库是否支持该功能。截至2019年12月,似乎没有任何主要的库实现了支持。以下是一些例子:


21
离子库怎么样? - abhit
12
我正在调用 preventDefault() - 是否有可能抑制此警告? - maja
2
@maja 不是问题的原因 - https://dev59.com/flcP5IYBdhLWcg3worn_#44339214 - Zze
21
谷歌地图JavaScript API第3版也会产生这些警告。问题正在 https://issuetracker.google.com/issues/63211698 跟踪。 (有点讽刺,考虑到谷歌Chrome正在警告谷歌地图JavaScript API生成的违规行为。) - Jochem Schulenklopper
12
为了消除这个警告,你可以使用 addEventListener('touchstart', this.callPassedFuntion, { passive: false }) - Shlomi Schwartz
显示剩余8条评论

24
以下库解决了这个问题。
只需将此代码添加到您的项目中即可。
<script type="text/javascript" src="https://unpkg.com/default-passive-events"></script>

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


找不到库。 - Hassam Saeed
这是唯一对我有效的方法 :) - Guntram

17

这将隐藏警告信息:

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

11
目标不是应该是阻止事件的发生吗?在解决问题之前,我不想隐藏信息。 - yardpenalty.com
1
我认为这是一个jquery库的问题。我想开发人员必须修复它。 但如果您能解决,请告诉我如何处理。非常感谢。 - Iván Rodríguez
当然,Ivan!是的。嘿,现在我很好奇...我正在使用d3插件,我得到了2300个违规。也许你的代码会有所帮助!我会随时向你汇报的! - yardpenalty.com
1
@yardpenalty.com,不,停止事件不是目标!警告指出您已放置了侦听器,但未指定它是否可能阻止事件的默认行为。如果您有需要调用preventDefault()的情况,则应指定passive: false。如果没有,请指定passive: true。只有在您没有指定任何一个时才会收到警告。如果您指定了passive: true并且调用了preventDefault(),则会导致错误并且默认值不会被阻止。在这里指定passive不是一种黑客技巧。它是解决方案。这就是警告所要求的! - tao
@tao 感谢您的评论。虽然已经过去了几年,但我一定会记住这个解决方案! - yardpenalty.com

8

对于使用jquery-ui-dragable和jquery-ui-touch-punch的问题,我像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') });
    }
};

8

对于那些被遗留问题困扰的人,请找到引发错误的代码行并添加{passive: true} - 例如:

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

转变为

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

7

只有在未指定 passive 时才会发出警告。

要消除此警告,您可以:

addEventListener('touchstart', this.callPassedFuntion, { 
  passive: false 
})

默认情况下,浏览器会监听preventDefault。因此,它会监听,但会提醒你:嘿,你可以在这里改进你的应用程序。如果不能,让我知道你不能(通过声明:passive: false)。

我从被接受的答案的评论中创建了这个答案,对于试图找到它的任何人来说可能更难找到。


2

除了基于触摸的事件外,您还可以添加基于滚动的修复措施,以防止谷歌页面评分将其标记为桌面版与移动版:

// 被动事件侦听器(两个标志设置中的轻微差异)

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 });
    }
};

1

我找到了一个在jQuery 3.4.1 slim上有效的解决方案。

取消代码压缩后,在第1567行的addEventListener函数中添加{passive: true},如下所示:

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

没有任何问题,并且Lighthouse审计不会抱怨监听器。


7
不要修改库的源代码,而应该覆盖它。 - Raptor
你如何在jQuery中实现对事件监听器的覆盖(override)? - AugustoM
没错,绝对同意不要改变库...只是说这是一个解决方案。 - Mark Lancaster

-1

我曾经遇到过同样的问题。然后我使用了这个:

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

希望你的问题也能得到解决。


1
请提供更多关于您回答的信息,而不仅仅是一个脚本链接。 - Dan Atkinson
回答中缺乏足够的描述。 - Darshan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接