Javascript 如何为同一个react组件添加多个事件侦听器?

Javascript 如何为同一个react组件添加多个事件侦听器?,javascript,reactjs,react-component,Javascript,Reactjs,React Component,如何更好地在同一组件中以更可重用的方式添加多个事件侦听器 componentDidMount: function() { window.addEventListener('resize', this.handleVisible); window.addEventListener('scroll', this.handleVisible); ... }, componentWillUnmount: function() { window.removeEvent

如何更好地在同一组件中以更可重用的方式添加多个事件侦听器

  componentDidMount: function() {
    window.addEventListener('resize', this.handleVisible);
    window.addEventListener('scroll', this.handleVisible);
...
  },

  componentWillUnmount: function() {
    window.removeEventListener('resize', this.handleVisible);
    window.removeEventListener('scroll', this.handleVisible);
...

  },

您可以创建如下自定义挂钩:

import { useEffect } from 'react'

export const useResizeScroll = callback => {
  useEffect(() => {
    window.addEventListener('resize scroll', callback);
    return () => window.removeEventListener('resize scroll', callback);
  }, [callback]);
};
const MyComponent = () => {
  useResizeScroll(handleVisible)

  function handleVisible() { ... }

  return (...)
}
useResizeScroll('resize scroll', handleVisible)
const { width } = useViewport()
然后在组件中实现它,如下所示:

import { useEffect } from 'react'

export const useResizeScroll = callback => {
  useEffect(() => {
    window.addEventListener('resize scroll', callback);
    return () => window.removeEventListener('resize scroll', callback);
  }, [callback]);
};
const MyComponent = () => {
  useResizeScroll(handleVisible)

  function handleVisible() { ... }

  return (...)
}
useResizeScroll('resize scroll', handleVisible)
const { width } = useViewport()
注意:

这将要求您转移到组件的hooks实现

因此,如果您使用的是
this.state={…}
,则需要学习如何使用React的
useState
钩子:

更新:

如果希望钩子更灵活,例如选择希望组件钩住的事件侦听器,则可以执行以下操作:

export const useResizeScroll = (eventListener, callback) => {
  useEffect(() => {
    window.addEventListener(eventListener, callback);
    return () => window.removeEventListener(eventListener, callback);
  }, [callback]);
};
然后像这样实现它:

import { useEffect } from 'react'

export const useResizeScroll = callback => {
  useEffect(() => {
    window.addEventListener('resize scroll', callback);
    return () => window.removeEventListener('resize scroll', callback);
  }, [callback]);
};
const MyComponent = () => {
  useResizeScroll(handleVisible)

  function handleVisible() { ... }

  return (...)
}
useResizeScroll('resize scroll', handleVisible)
const { width } = useViewport()
更高级的用例:

您还可以通过使用React上下文来改进定制钩子。下面是一个实现跟踪窗口宽度的钩子的示例

import React, { createContext, useContent, useEffect, useState } from 'react'

const ViewportContext = createContext({ width: window.innerWidth })

export const ViewportProvider = ({ children }) => {
  const [width, setWidth] = useState(window.innerWidth)

  function handleResize() {
    setWidth(window.innerWidth)
  }

  useEffect(() => {
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [])

  return (
    <ViewportContext.Provider value={{ width }}>
      {children}
    </ViewportContext.Provider>
  )
}

export const useViewport = () => {
  const { width } = useContext(ViewportContext)
  return { width }
}
这将为您提供足够的信息来构建与您的用例相匹配的自定义挂钩。

这:

window.addEventListener('resize scroll', callback); 
不适合我

我必须做:

window.addEventListener('resize', callback);
window.addEventListener('scroll', callback);
但这起到了作用:

window.removeEventListener('resize scroll', handleResize) 

您可以为此创建自定义挂钩。
window.addEventListener('resize scroll',this.handlevible)谢谢回复。因此,如果还有其他事件侦听器,我可以简单地添加到同一个钩子中,但在组件中添加如下内容?useResizeScroll(可手动);useResizeScroll(handlehidden)如果有其他回调的情况吗?我将更新使用不同事件侦听器的用例。我有点困惑。所以我的问题是,我是否可以用分号分隔的不同回调调用同一个钩子两次。这里也不应该是return()=>window.removeEventListener('eventlistener',callback);更新的部分也一样?是的,对不起,我会解决的。为什么不将多个回调组合到一个函数中,并使其成为回调函数呢?回调是完全不同的,没有办法将它们混合在一个函数中。