如何在插件中复用内置的管理面板组件

页面摘要: 内置的管理面板组件通过组件注册表(component registry)暴露,你可以使用 useStrapiApp hook 读取该注册表。本指南以媒体库对话框(MediaLibraryDialog)为例:从注册表中获取它,然后渲染它来复用 Strapi 的资源选择对话框,也可以使用 initiallySelectedAssets 属性预先选中资源。

开发 Strapi 插件 或自定义管理面板时,你可能希望复用 Strapi 已经在管理面板中提供的内置 React 组件,而不是自己从零构建。内置组件通过管理面板的组件注册表暴露,你可以使用 useStrapiApp hook 来访问它。

本指南以媒体库对话框(MediaLibraryDialog)为例,但同样的方法适用于在管理面板中注册的任何组件。

从注册表访问组件

内置的管理面板组件存储在 Strapi 应用上下文(app context)的 components 对象中。使用 useStrapiApp hook 读取它,传入消费组件的名称和一个选择器(selector):

import { useStrapiApp } from '@strapi/admin/strapi-admin';

const components = useStrapiApp('MyCustomComponent', (state) => state.components);
const MediaLibraryDialog = components['media-library'];

useStrapiApp 的第一个参数是一个用于标识消费方的标签(用于错误消息);第二个参数是返回你所需的上下文部分的选择器。

复用媒体库对话框

MediaLibraryDialog 组件会打开管理面板各处使用的同一个资源选择对话框。它接受以下属性:

PropTypeDescription
onSelectAssets(selectedAssets: File[]) => void必填。当用户确认选择时,会随用户选中的资源一起被调用。
onClose() => void必填。当对话框关闭时被调用。
initiallySelectedAssetsFile[]可选。对话框打开时要预先选中的媒体库资源对象。
allowedTypesstring[]可选。限制可被选择的资源类型。默认为 ['files', 'images', 'videos', 'audios']。
multipleboolean可选。允许一次选择多个资源。默认为 true。
NOTE

initiallySelectedAssets 期望的是完整的媒体库资源对象(其结构与 Upload API 返回的结构相同),而不仅仅是 id 和 name。

以下示例从一个自定义组件中渲染该对话框,并在打开时预先选中资源:

import { useState } from 'react';
import { useStrapiApp } from '@strapi/admin/strapi-admin';

export function MyCustomComponent() {
  const [isMediaLibraryOpen, setIsMediaLibraryOpen] = useState(false);
  const components = useStrapiApp('MyCustomComponent', (state) => state.components);
  const MediaLibraryDialog = components['media-library'];

  // Assets to pre-select when the dialog opens.
  // Each entry is a full Media Library asset object, not just an id and name.
  const initialAssets = [
    { id: 1, name: 'image1.jpg' /* ...other asset fields */ },
    { id: 2, name: 'image2.png' /* ...other asset fields */ },
  ];

  const handleSelectAssets = (assets) => {
    // Handle the assets the user selected
    console.log('Selected assets:', assets);
    setIsMediaLibraryOpen(false);
  };

  return (
    <>
      <button type="button" onClick={() => setIsMediaLibraryOpen(true)}>
        Open the Media Library
      </button>
      {isMediaLibraryOpen && (
        <MediaLibraryDialog
          initiallySelectedAssets={initialAssets}
          onSelectAssets={handleSelectAssets}
          onClose={() => setIsMediaLibraryOpen(false)}
        />
      )}
    </>
  );
}

预先选中资源可确保当用户从你的自定义组件打开媒体库对话框时,之前选中的条目能够显示出来。