React警告非被动事件监听器阻止了滚动的“touchstart”

7
我有一个带有 Material-UI 滑块的 React 组件。每次渲染组件时,控制台都会显示以下警告信息:“Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive”(为滚动阻塞的“touchstart”事件添加了非被动式事件监听器。考虑将事件处理程序标记为“被动”以使页面更具响应性)。
如何解决这个问题?
参考图片:控制台中的警告信息截图
3个回答

6

许多库和框架默认添加了非被动事件监听器。你无法做太多事情。相反,建议使用高度灵活和可配置的 passive-events-support 包来调试和使事件监听器变为被动,而无需触及第三方源代码。

首先,在安装该包后,调试触摸和滚动事件监听器及其参数:

import { passiveSupport } from 'passive-events-support/src/utils'
passiveSupport({ debug: true })

这应该会在控制台记录所有事件监听器

[Passive Events Support] Non-passive Event Listener
  element: div.some-element
  event: 'touchstart'
  handler:
    fn: ƒ (e)
    fnArgument: 'e'
    fnContent: 'console.log(e)'
    fnPrevented: false
  arguments: false

注意 arguments 参数,如果它是 falseundefined 或者没有 passive 参数的对象,这个事件会导致你的浏览器抛出一个警告并影响滚动的性能。

要修复它,只需使用该软件包和记录的信息将此事件侦听器转换为被动模式:

import { passiveSupport } from 'passive-events-support/src/utils'
passiveSupport({
  debug: false,
  // add this one
  listeners: [
    {
      element: 'div.some-element',
      event: 'touchstart'
    }
  ]
})

请注意,调用 preventDefault() 的事件监听器不应被标记为"passive",但是为了修复警告,仍应将passive参数的值设为false

默认情况下,该包会检查是否从处理程序本身阻止它,但是如果事件监听器是从处理程序内部调用的方法中阻止的,则该包会失去追踪。 若要强制分配 passive: false,只需将 prevented: true 参数传递给 listeners 项:

passiveSupport({
  //...
  listeners: [
    {
      element: 'div.some-element',
      event: 'touchstart',
      prevented: true
    }
  ]
})

对我来说,这个包修复了由Materialize和jQuery引起的所有警告。希望它也能对你有所帮助。


0

React不支持被动事件监听器。你需要做的是获取真实DOM的ref,并使用{passive:true}作为选项附加事件监听器。在销毁组件之前(实际上在componentWillUnmount中)别忘了分离事件监听器。


@user12083483 请参考此文档:https://reactjs.org/docs/refs-and-the-dom.html。您需要创建一个 ref 并将其分配给您想要分配事件监听器的 dom(jsx 标记)。 - Pengson
谢谢你的帮助。 我尝试了以下代码: const slider = useRef(null); useEffect(() => { slider.current.addEventListener('touchstart', handleTouchStart, { passive: true }) }, []) 但是它没有起作用...我做错了什么吗? 在我看来,警告来自于material-ui Slider.js文件 - slider.addEventListener('touchstart', handleTouchStart);(当我在控制台中按下警告时,会跳转到这里...) - user12083483
@user12083483,你能否创建一个在线示例,例如codesandbox,这样我就可以通过检查你的代码来帮助你? - Pengson
警告会在控制台中以详细模式显示。但是当我在CodeSandbox中创建一个示例时,没有警告。 - user12083483
我添加了一张控制台警告信息的图片。 - user12083483
显示剩余2条评论

0

您可以查看 GitHub 分支(问题#20)以获取详细信息,了解如何修复问题,以下是其操作:

修改 sidenav.js 的第 132、134 和 136 行。

从以下内容进行更改:

this.dragTarget.addEventListener('touchmove', this._handleDragTargetDragBound);
this._overlay.addEventListener('touchmove', this._handleCloseDragBound);
this.el.addEventListener('touchmove', this._handleCloseDragBound);

到:

this.dragTarget.addEventListener('touchmove', this._handleDragTargetDragBound, { passive: true});
this._overlay.addEventListener('touchmove', this._handleCloseDragBound, { passive: true});
this.el.addEventListener('touchmove', this._handleCloseDragBound, { passive: true});

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