【问题标题】: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
});

但我仍然收到此警告。

【问题讨论】:

    标签: javascript jquery angularjs touch hammer.js


    【解决方案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 月,似乎没有任何主要库已实现支持。一些例子:

    【讨论】:

    • 离子库怎么样?
    • 我正在打电话给preventDefault() - 是否可以取消此警告?
    • 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中实现对事件监听器的覆盖?
            • 对,绝对同意不改库……就说解决办法
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-12
            • 1970-01-01
            • 1970-01-01
            • 2015-08-13
            • 1970-01-01
            相关资源
            最近更新 更多