簡體   English   中英

將事件偵聽器添加到具有給定屬性的每個組件

[英]Add event listener to every Component with a given property

我有很多帶有onKeyup事件監聽器的組件,然后檢查鍵是否是Tab ,如果是,則采取行動。 我想稍微抽象一下並創建一個onTab屬性,其中的值是執行該操作的回調 function。 但是,重要的是,我想要“這個鍵是Tab嗎?” 抽象出來的邏輯。 我的想法是我可以編寫這樣的邏輯:“在初始化此組件時,檢查它是否具有onTab屬性,如果有,則使用 X 邏輯創建一個onKeyup事件偵聽器以觸發onTab回調。” 但是,我不確定該怎么做。

任何人都可以幫忙嗎?

我可以想到 3 種解決方案,每種都有其優點和復雜性。

首先,使用鈎子:

// use-on-tab.js

const useOnTab = function (callback) {
  let listener = function (event) {
    if (event.code === 'Enter') {
      callback()
    }
  }

  return listener
}

export default useOnTab
// Foo.js

import useOnTab from './use-on-tab'

const Foo = function () {
  let onTab = useOnTab(() => console.log('foo'))
  return <div onKeyUp={onTab} tabIndex="0">Foo</div>
}

export default Foo

這個方案很簡單,可以隱藏檢查key的邏輯,只通過回調。 但是您仍然必須手動調用useOnTab並在每個組件上添加onKeyUp屬性。


二、使用HOC:

// with-on-tab.js

const withOnTab = function (WrappedComponent) {
  let createListener = function (callback) {
    return function (event) {
      if (event.code === 'Enter') {
        callback()
      }
    }
  }

  return function ({ onTab, ...props }) {
    return <WrappedComponent {...props} onKeyUp={createListener(onTab)} />
  }
}

export default withOnTab
// Bar.js

import withOnTab from './with-on-tab'

const Bar = function (props) {
  return <div tabIndex="0" {...props}>Bar</div>
}

export default withOnTab(Bar)
<Bar onTab={() => console.log('bar')} />

閱讀有關高階組件的更多信息。


最后一個是自定義 JSX:

// jsx-dev-runtime.js

import * as ReactJSXRuntimeDev from 'react/jsx-dev-runtime'

export const Fragment = ReactJSXRuntimeDev.Fragment

export function jsxDEV(
  type,
  props,
  key,
  isStaticChildren,
  source,
  self
) {
  let newProps = props

  if (Object.prototype.hasOwnProperty.call(props, 'onTab')) {
    let { onTab, ...props } = newProps

    newProps = {
      ...props,
      onKeyUp: event => {
        if (event.code === 'Enter') {
          onTab()
        }
      }
    }
  }

  return ReactJSXRuntimeDev.jsxDEV(
    type,
    newProps,
    key,
    isStaticChildren,
    source,
    self
  )
}
// Baz.js

const Baz = function (props) {
  return <div tabIndex="0" {...props}>Baz</div>
}

export default Baz
/** @jsxImportSource custom-jsx-library */

<Baz onTab={() => console.log('baz')} />

我從@emotion/react得到這個想法,它必須處理css道具。 Github

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM