compose 包是一组实用的 Hooks 和 高阶组件 (HOCs),可用于包装你的 WordPress 组件并提供一些基本功能,例如:状态、实例 ID、纯组件等。
compose 函数灵感来源于 Lodash 的 flowRight,其工作方式相同。它源自函数式编程,允许你组合任意数量的函数。你也可以将其理解为函数的分层;compose 会先执行最后一个函数,然后依次向前通过之前的函数,将每个函数的结果向上传递。
以下示例说明了两个函数的组合:
const compose = ( f, g ) => x
=> f( g( x ) );
以下是来自 Gutenberg 的 PluginSidebar 组件 中 compose 使用的简化示例:
使用 compose:
const applyWithSelect = withSelect( ( select, ownProps ) => {
return doSomething( select, ownProps );
} );
const applyWithDispatch = withDispatch( ( dispatch, ownProps ) => {
return doSomethingElse( dispatch, ownProps );
} );
export default compose(
withPluginContext,
applyWithSelect,
applyWithDispatch
)( PluginSidebarMoreMenuItem );
如果不使用 compose,代码将如下所示:
const applyWithSelect = withSelect( ( select, ownProps ) => {
return doSomething( select, ownProps );
} );
const applyWithDispatch = withDispatch( ( dispatch, ownProps ) => {
return doSomethingElse( dispatch, ownProps );
} );
export default withPluginContext(
applyWithSelect( applyWithDispatch( PluginSidebarMoreMenuItem ) )
);
安装
安装模块
npm install @wordpress/compose --save
本包假设你的代码将在 ES2015+ 环境中运行。如果你使用的是对这类语言特性和 API 支持有限或完全不支持的环境,请在代码中包含 @wordpress/babel-preset-default 随附的 polyfill。
API
更多详细信息,请参阅每个高阶组件的 README 文件。可用组件位于此处。
compose
将多个高阶组件组合成单个高阶组件。执行从右到左的函数组合,每次连续调用都会接收前一次调用的返回值。
这灵感来源于 lodash 的 flowRight 函数。
相关
createHigherOrderComponent
给定一个将组件映射到增强组件及修饰符名称的函数,返回带有生成的 displayName 的增强组件。
参数
- mapComponent
( Inner: TInner ) => TOuter:将组件映射到增强组件的函数。 - modifierName
string:用于生成显示名称的种子名称。
返回
- 具有分配生成的 display name 的组件类。
debounce
Lodash 的 debounce 的简化且类型正确的版本,始终使用计时器而不是有时使用 rAF。
创建一个防抖函数,该函数会在距离上次调用防抖函数后经过 wait 毫秒后才调用 func。防抖函数带有一个 cancel 方法用于取消延迟的 func 调用,以及一个 flush 方法用于立即调用它们。提供 options 以指示是否应在 wait 超时的前沿和/或尾部边缘调用 func。func 使用传递给防抖函数的最后一个参数进行调用。后续对防抖函数的调用返回上一次 func 调用的结果。
注意:如果 leading 和 trailing 选项为 true,则仅当在 wait 超时期间防抖函数被调用多次时,func 才会在超时的尾部边缘被调用。
如果 wait 为 0 且 leading 为 false,则 func 调用会被推迟到下一个 tick,类似于超时为 0 的 setTimeout。
参数
- func
Function:要防抖的函数。 - wait
number:要延迟的毫秒数。 - options
Partial< DebounceOptions >:选项对象。 - options.leading
boolean:指定在超时的前沿边缘调用。 - options.maxWait
number:func在被调用之前允许的最大延迟时间。 - options.trailing
boolean:指定在超时的尾部边缘调用。
返回
- 返回新的防抖函数。
ifCondition
高阶组件创建器,创建一个新组件,当满足给定条件或使用给定的可选 prop 名称时进行渲染。
用法
type Props = { foo: string };
const Component = ( props: Props ) => <div>{ props.foo }</div>;
const ConditionalComponent = ifCondition( ( props: Props ) => props.foo.length !== 0 )( Component );
<ConditionalComponent foo="" />; // => null
<ConditionalComponent foo="bar" />; // => <div>bar</div>;
参数
- predicate
( props: Props ) => boolean:用于测试条件的函数。
返回
- 高阶组件。
observableMap
ObservableMap 的构造函数(工厂),这是一种类似 map 的键值数据结构,其中各个条目是可观察的:使用 subscribe 方法,你可以订阅特定键的更新。每个订阅者始终观察一个特定的键,并且不会收到 ObservableMap 中任何不相关更改(针对不同的键)的通知。
返回
ObservableMap< K, V >:ObservableMap类型的新实例。
pipe
将多个高阶组件组合成单个高阶组件。执行从左到右的函数组合,每次连续调用都会接收前一次调用的返回值。
这灵感来源于 lodash 的 flow 函数。
相关
privateApis
私有 @wordpress/compose API。
pure
已弃用 请改用
memo或PureComponent。
给定一个组件,返回增强后的组件,该组件仅在 props/state 更改时才重新渲染。
throttle
Lodash 的 throttle 的简化且类型正确的版本,始终使用计时器而不是有时使用 rAF。
创建一个节流函数,该函数每隔 wait 毫秒最多调用一次 func。节流函数带有一个 cancel 方法用于取消延迟的 func 调用,以及一个 flush 方法用于立即调用它们。提供 options 以指示是否应在 wait 超时的前沿和/或尾部边缘调用 func。func 使用传递给节流函数的最后一个参数进行调用。后续对节流函数的调用返回上一次 func 调用的结果。
注意:如果 leading 和 trailing 选项为 true,则仅当在 wait 超时期间节流函数被调用多次时,func 才会在超时的尾部边缘被调用。
如果 wait 为 0 且 leading 为 false,则 func 调用会被推迟到下一个 tick,类似于超时为 0 的 setTimeout。
参数
- func
Function:要节流的函数。 - wait
number:节流调用的毫秒数。 - options
Partial< ThrottleOptions >:选项对象。 - options.leading
boolean:指定在超时的前沿边缘调用。 - options.trailing
boolean:指定在超时的尾部边缘调用。
返回
- 返回新的节流函数。
useAsyncList
React hook 返回一个数组,其项目从源数组异步追加。出于性能原因,如果我们希望异步渲染项目列表,这种行为非常有用。
参数
- list
T[]: 源数组。 - config
AsyncListConfig: 配置对象。
返回
T[]: 异步数组。
useConstrainedTabbing
在对话框/模态框中,Tab 键导航必须限制在包装元素的内容范围内。此 Hook 将行为添加到返回的 ref 中。
用法
import { useConstrainedTabbing } from '@wordpress/compose';
const ConstrainedTabbingExample = () => {
const constrainedTabbingRef = useConstrainedTabbing()
return (
<div ref={ constrainedTabbingRef }>
<Button />
<Button />
</div>
);
}
返回
React.RefCallback< Element >: 元素 Ref。
useCopyOnClick
已弃用
当元素被点击时,将文本复制到剪贴板。
参数
- ref
RefObject< string | Element | NodeListOf< Element > | null >: 带有元素的引用。 - text
string | ( () => string ): 要复制的文本。 - timeout
number: 重置返回状态的可选超时时间。默认为 4 秒。
返回
boolean: 文本是否已被复制。超时后重置。
useCopyToClipboard
当元素被点击时,将给定文本复制到剪贴板。
参数
- text
string | ( () => string ): 要复制的文本。如果文本尚不可用且计算昂贵,请使用函数。 - onSuccess
() => void: 文本复制成功时调用。
返回
RefCallback< T >: 分配给目标元素的 ref。
useDebounce
对函数进行防抖处理,类似于 Lodash 的 debounce。如果任何参数(包括要防抖的函数)发生变化,将返回一个新的防抖函数并取消任何计划的调用,因此请将组件渲染期间创建的函数包装在 useCallback 中。
相关
参数
- fn
TFunc: 要防抖的函数。 - wait
number: 延迟的毫秒数。 - options
DebounceOptions: 选项对象。
返回
DebouncedFunc< TFunc >: 防抖函数。
useDebouncedInput
用于需要在输入值之前进行防抖处理的输入字段的辅助 Hook。
参数
- defaultValue 要使用的默认值。
返回
[ string, ( value: string ) => void, string ]: 输入值、设置器和防抖后的输入值。
useDisabled
在某些情况下,例如区块预览,所有可聚焦的 DOM 元素(输入字段、链接、按钮等)都需要禁用。此 Hook 将禁用嵌套 DOM 元素的行为添加到返回的 ref 中。
如果可以,请优先使用 inert HTML 属性。
用法
import { useDisabled } from '@wordpress/compose';
const DisabledExample = () => {
const disabledRef = useDisabled();
return (
<div ref={ disabledRef }>
<a href="#">此链接的 tabindex 将设置为 -1</a>
<input
placeholder="此输入字段将添加 disabled 属性。"
type="text"
/>
</div>
);
};
参数
- config
Object: 配置对象。 - config.isDisabled
boolean=: 元素是否应被禁用。
返回
React.RefCallback<HTMLElement>: 元素 Ref。
useEvent
创建一个稳定的回调函数,可以访问最新状态,并可用于事件处理程序和效果回调中。在渲染阶段使用时会抛出异常。
用法
function Component( props ) {
const onClick = useEvent( props.onClick );
useEffect( () => {
onClick();
// 当 props.onClick 更新时,不会再次触发效果。
}, [ onClick ] );
// 当 props.onClick 更新时,Button 不会重新渲染(如果 `Button`
// 包裹在 `React.memo` 中)。
return <Button onClick={ onClick } />;
}
参数
- callback
T: 要包装的回调函数。
useFocusableIframe
当 iframe 获得焦点时,派发一个冒泡的 focus 事件。像往常一样在 iframe 或父元素上使用 onFocus。
返回
RefCallback< HTMLIFrameElement >: 传递给 iframe 的 Ref。
useFocusOnMount
确定元素挂载时的焦点行为。
用法
import { useFocusOnMount } from '@wordpress/compose';
const WithFocusOnMount = () => {
const ref = useFocusOnMount();
return (
<div ref={ ref }>
<Button />
<Button />
</div>
);
};
参数
- focusOnMount
useFocusOnMount.Mode: 行为模式。默认为"firstElement",聚焦于内部第一个可 Tab 的元素;"firstInputElement"聚焦于内部第一个值控件;true聚焦于元素本身;false不执行任何操作。
返回
- Ref 回调。
useFocusReturn
添加卸载时将焦点返回到先前拥有它的元素的行为,这对于菜单或对话框等角色是预期的。
用法
import { useFocusReturn } from '@wordpress/compose';
const WithFocusReturn = () => {
const ref = useFocusReturn()
return (
<div ref={ ref }>
<Button />
<Button />
</div>
);
}
参数
- onFocusReturn
() => void: 覆盖默认的返回行为。
返回
React.RefCallback< HTMLElement >: 元素 Ref。
useInstanceId
指定 useInstanceId 函数 签名。
更准确地说,useInstanceId 区分三种不同的签名:
- 当仅提供 object 时,返回值是一个数字
- 当提供 object 和 prefix 时,返回值是一个字符串
- 当提供 preferredId 时,返回值是 preferredId 的类型
参数
- object
object: 用于创建 ID 的对象引用。
useIsomorphicLayoutEffect
在支持服务器端渲染组件 (SSR) 时,首选使用此 Hook 而不是直接使用 useLayoutEffect,因为目前 React 在使用 useLayoutEffect 时会发出警告。
useKeyboardShortcut
附加键盘快捷键处理程序。
相关
- https://craig.is/killing/mice#api.bind 关于
callback参数的信息。
参数
- shortcuts
string[] | string: 键盘快捷键。 - callback
( e: ExtendedKeyboardEvent, combo: string ) => void: 快捷键回调。 - options
Partial< KeyboardShortcutConfig >: 快捷键选项。 - options.bindGlobal
Partial< KeyboardShortcutConfig >[ 'bindGlobal' ]: - options.eventName
Partial< KeyboardShortcutConfig >[ 'eventName' ]: - options.isDisabled
Partial< KeyboardShortcutConfig >[ 'isDisabled' ]: - options.target
Partial< KeyboardShortcutConfig >[ 'target' ]:
useMediaQuery
运行媒体查询并在其值变化时返回该值。
参数
- query
[string]: 媒体查询。 - view
[Window | undefined]: Window 实例,否则默认为全局 window
返回
boolean: 媒体查询的返回值。
useMergeRefs
将多个 refs 合并为一个 ref 回调。
它还确保合并的 ref 回调仅在它们发生变化时(由于 useCallback 依赖项更新)或当 ref 值发生变化时才被调用,正如 React 在向组件传递单个 ref 回调时所做的事情一样。
正如预期的那样,如果您在每次渲染时都传递一个新函数,ref 回调将在每次渲染后被调用。
如果您不希望 ref 回调在每次渲染后都被调用,请用 useCallback( callback, dependencies ) 将其包装。当依赖项发生变化时,旧的 ref 回调将以 null 调用,新的 ref 回调将以相同的值调用。
内部 ref 回调可以返回一个清理函数(React 19 的 ref 回调清理模式)。当 ref 回调返回一个函数时,该函数将在拆卸阶段(节点更改、依赖项更改或卸载)被调用,而不是以 null 作为参数调用回调。那些不返回清理函数的回调在拆卸时仍会像以前一样接收 null。
还可以通过简单地不传递 ref 来禁用 ref(及其行为)。
const ref = useCallback( ( node ) => {
node.addEventListener( ... );
return () => {
node.removeEventListener( ... );
};
}, [ ...dependencies ] );
const otherRef = useRef();
const mergedRefs = useMergeRefs( [
enabled && ref,
otherRef,
] );
return <div ref={ mergedRefs } />;
参数
- refs
Ref< T >[]: 要合并的 refs。
返回
RefCallback< T >: 合并后的 ref 回调。
useObservableValue
允许你观察 ObservableMap 中条目的 React hook。该 hook 返回与键对应的当前值,如果没有存储值则返回 undefined。它还会观察值的变化,并在值发生变化时触发调用组件的更新。
参数
- map
ObservableMap< K, V >: 要观察的ObservableMap。 - name
K: 要观察的 map 键。
返回
V | undefined: 对应于请求的 map 键的值。
usePrevious
获取上一次渲染时的值。基于 https://usehooks.com/usePrevious/。
参数
- value
T: 要跟踪的值。
返回
T | undefined: 上一次渲染时的值。
useReducedMotion
返回用户是否偏好减少运动的 hook。
返回
boolean: 减少运动偏好值。
useRefEffect
类似 Effect 的 ref 回调。就像使用 useEffect 一样,这允许你返回一个清理函数,以便在 ref 更改或其中一个依赖项更改时运行。ref 将作为参数提供给回调函数。它与 useEffect 的主要区别在于,当 ref 更改时 useEffect 回调不会被调用,但此方法会如此。将返回的 ref 回调作为组件的 ref 传递,并使用 useMergeRefs 合并多个 refs。
值得注意的是,如果依赖项数组为空,严格来说不需要清理事件处理程序(例如),因为节点将被移除。如果你添加了依赖项,则这是必要的,因为 ref 回调将对同一节点多次调用。
参数
- callback
( node: TElement ) => ( () => void ) | void: 带有 ref 作为参数的回调。 - dependencies
DependencyList: 回调的依赖项。
返回
RefCallback< TElement | null >: Ref 回调。
useResizeObserver
为 HTML 或 SVG 元素设置 ResizeObserver。
将返回的设置器作为回调 ref 传递给你要观察的 React 元素,或者在布局 effect 中使用它以应对高级用例。
用法
const setElement = useResizeObserver(
( resizeObserverEntries ) => console.log( resizeObserverEntries ),
{ box: 'border-box' }
);
<div ref={ setElement } />;
// 设置器还可以以其他方式使用,例如:
useLayoutEffect( () => {
setElement( document.querySelector( `data-element-id="${ elementId }"` ) );
}, [ elementId ] );
参数
- callback
ResizeObserverCallback:ResizeObserver回调 – MDN 文档。 - options
ResizeObserverOptions: 调用时传递给ResizeObserver.observe的选项 – MDN 文档。更改将被忽略。
useStateWithHistory
具有撤销/重做历史的 useState。
参数
- initialValue
T: 初始值。
返回
- Value, setValue, hasUndo, hasRedo, undo, redo。
useThrottle
对函数进行节流,类似于 Lodash 的 throttle。如果任何参数(包括要节流的函数)发生更改,将返回一个新的节流函数并取消任何已调度的调用,因此请将渲染期间创建的函数包装在组件的 useCallback 中。
相关
参数
- fn
TFunc: 要节流的函数。 - wait
number: 节流调用的毫秒数。 - options
ThrottleOptions: 选项对象。
返回
DebouncedFunc< TFunc >: 节流后的函数。
useViewportMatch
如果视口匹配给定的查询,则返回 true,否则返回 false。
用法
useViewportMatch( 'huge', '<' );
useViewportMatch( 'medium' );
参数
- breakpoint
Breakpoint: 断点大小名称。 - operator
ViewportOperator: 视口运算符。 - view
Window | undefined: 在其中执行视口匹配的 Window 实例。
返回
boolean: 视口是否匹配查询。
useWarnOnChange
执行对象新值与旧值之间浅比较的 hook,如果有差异,则将其打印到控制台。这在性能相关工作中很有用,用于检查组件重新渲染的原因。
用法
function MyComponent( props: Record< string, any > ) {
useWarnOnChange( props );
return 'Something';
}
参数
- object
Record< string, any > | any[]: 要比较更改的对象。 - prefix
string: 仅在控制台日志显示时的前缀。
withGlobalEvents
已弃用
高阶组件创建器,给定一个 DOM 事件类型和值的对象,这些值对应于组件上回调函数的名称,它将创建或更新一个窗口事件处理程序,以便在事件发生时调用回调。代表消费开发者,高阶组件管理组件卸载时的解绑,并为整个应用程序绑定最多单个事件处理程序。
参数
- eventTypesToHandlers
Record<keyof GlobalEventHandlersEventMap, string>: 键为 DOM 事件类型的对象,值为原始组件实例上处理该事件的函数名称。
返回
any: 高阶组件。
withInstanceId
用于按组件提供唯一实例 ID 的高阶组件。
withSafeTimeout
用于提供和管理应绑定到组件生命周期的延迟函数调用的高阶组件。
withState
已弃用 请改用
useState。
用于通过 props 提供和管理组件内部状态的高阶组件。
参数
- initialState
any: 组件的可选初始状态。
返回
any: 接受一个组件的高阶组件包装器,该组件接受 state props + 其自身的 props +setState,并返回一个仅接受自身 props 的组件。
贡献到此包
这是 Gutenberg 项目的一个独立包。该项目组织为一个 monorepo。它由多个自包含的软件包组成,每个包都有特定的用途。此 monorepo 中的包发布到 npm,并被 WordPress 以及其他软件项目使用。
要了解有关为此包或整个 Gutenberg 做出贡献的更多信息,请阅读项目的主 贡献者指南。