[英]Add event listener to every Component with a given property
I have a lot of Components with onKeyup
event listeners, which then check to see if the key was Tab
and if so, take an action.我有很多带有
onKeyup
事件监听器的组件,然后检查键是否是Tab
,如果是,则采取行动。 I'd like to abstract that a bit and create an onTab
property, where the value is a callback function that executes that action.我想稍微抽象一下并创建一个
onTab
属性,其中的值是执行该操作的回调 function。 But, importantly, I'd like the "was this key a Tab
?"但是,重要的是,我想要“这个键是
Tab
吗?” logic to be abstracted away.抽象出来的逻辑。 My thought was that I could write logic that said "When initializing this Component, check if it has an
onTab
property, and if so, create an onKeyup
event listener with X logic to trigger the onTab
callback."我的想法是我可以编写这样的逻辑:“在初始化此组件时,检查它是否具有
onTab
属性,如果有,则使用 X 逻辑创建一个onKeyup
事件侦听器以触发onTab
回调。” However, I'm unsure how to do that.但是,我不确定该怎么做。
Can anyone help?任何人都可以帮忙吗?
I can think of 3 solutions, each with its advantages and complexity.我可以想到 3 种解决方案,每种都有其优点和复杂性。
First, use hook:首先,使用钩子:
// 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
This solution is quite simple, you can hide the logic of checking key and only pass the callback.这个方案很简单,可以隐藏检查key的逻辑,只通过回调。 But you still have to manually call
useOnTab
and add onKeyUp
prop on every components.但是您仍然必须手动调用
useOnTab
并在每个组件上添加onKeyUp
属性。
Second, use HOC:二、使用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')} />
Read more about Higher-Order Components .阅读有关高阶组件的更多信息。
And the last one is custom JSX:最后一个是自定义 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')} />
I get this idea from @emotion/react
which has to deal with the css
prop.我从
@emotion/react
得到这个想法,它必须处理css
道具。 Github Github
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.