繁体   English   中英

使用更高阶的组件为每个组件添加事件侦听器

[英]Using a higher order component to add event listeners per component

我的应用程序中有一些组件,可以处理来自键盘的一些用户输入。 为此,我创建了以下功能:

export default function withKeydownEventHandler (handler) {
  id = id + 1
  return lifecycle({
    componentWillMount () {
      $(window).on(`keydown.${id}`, evt => handler(evt))
    },
    componentWillUnmount () {
      $(window).off(`keydown.${id}`)
    }
  })
}

这样可以正常工作,但处理程序同时被激活用于不同的组件。 因此,如果我的处理程序在每个组件中执行不同的操作,每当我单击一个按钮时,它将同时从两个组件中触发。 此外,一旦卸下一个组件,HoC将不再起作用。

例如,假设我有以下两个容器:

export default compose(
  withKeydownEventHandler((evt, props) => {
    console.warn('hi from Component 1')
  }),
  withProps(() => {
    // stuff
  })
)(Component1)

export default compose(
  withKeydownEventHandler((evt, props) => {
    console.warn('hi from Component 2')
  }),
  withProps(() => {
    // stuff
  })
)(Component2)

如果我点击整个应用程序中的任何按钮,我将得到以下输出:

来自组件1

来自组件2

另一方面,一旦其中一个组件卸载,我就不再发生任何事件。

我究竟做错了什么? 如何通过可在整个应用程序中重复使用的HoC获取keydown事件处理程序?

首先,我可以提请您注意您的id被设置为全局变量。 您确定要将这样的变量名称作为全局变量吗?

其次,你使用$(window).on('keydown.${id}', evt => handler(evt))将keydown事件绑定到windows,这解释了你不想要的行为。 您需要将其与您希望处理程序操作的特定组件绑定一次。

最后,为什么不创建一个HOC类并有条件地添加事件监听器? 如下:

// src/Hoc.jsx

export default function(WrapperComponent) {
  return class extends Component {
    componentWillMount () {
      const { onKeyDownHandler } = this.props;
      if (isKeyDownEventNeeded) {
         this.comp.addEventListener("keydown", onKeyDownHandler);
      }
    }
    componentWillUnmount () {
      const { onKeyDownHandler } = this.props;
      if (isKeyDownEventNeeded) {
         this.comp.removeEventListener("keydown", onKeyDownHandler);
      }
    }
    render() {
        const { onKeyDownHandler } = this.props;
        if (onKeyDownHandler) { 
            // a "ref" callback which assigns the mounted 
            // Element to a prop "comp" whicu can be used later to add the DOM listener to.
            return <WrapperComponent ref={elem => this.comp = elem} {...this.props} />
        }
        return <WrapperComponent {...this.props} />
    }
}

export default HighOrderComponent;

然后

// somewhere-else.js

import highOrderComponent from 'src/Hoc'    
highOrderComponent(<Component1 onKeyDownHandler={() => console.log('hey, Component 1'} />
highOrderComponent(<Component2 onKeyDownHandler={() => console.log('hey, Component 2'} />

有关如何查看此答案的更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM