Skip to main content

管理面板 API:注入区域

🌐 Admin Panel API: Injection zones

Page summary:

注入区域是在管理界面中预定义的区域,插件可以在这些区域注入 React 组件。使用 getPlugin('content-manager').injectComponent() 来扩展内置视图,或在 registerPlugin 中使用 injectionZones 定义自己的区域。

🌐 Injection zones are predefined areas in the admin UI where plugins can inject React components. Use getPlugin('content-manager').injectComponent() to extend built-in views, or define your own zones with injectionZones in registerPlugin.

插件可以通过将自定义 React 组件注入预定义区域来扩展和自定义现有的管理面板部分。这使你能够在不修改核心代码的情况下,为 Strapi 的内置界面添加功能。

🌐 Plugins can extend and customize existing admin panel sections by injecting custom React components into predefined areas. This allows you to add functionality to Strapi's built-in interfaces without modifying core code.

Prerequisites

在深入了解本页的概念之前,请确保你已经:

🌐 Before diving deeper into the concepts on this page, please ensure you have:

Note

注入区域在 register 生命周期函数中定义,但组件在 bootstrap 生命周期函数中注入。

🌐 Injection zones are defined in the register lifecycle function, but components are injected in the bootstrap lifecycle function.

注入区与内容管理器 API

🌐 Injection zones vs. Content Manager APIs

tl;dr

要向内容管理器添加面板、操作或按钮,内容管理器 APIaddDocumentActionaddEditViewSidePanel 等)通常比注入区更稳健且类型更明确。当需要将组件插入内容管理器 API 未覆盖的特定 UI 区域时,请使用注入区。

🌐 For adding panels, actions, or buttons to the Content Manager, the Content Manager APIs (addDocumentAction, addEditViewSidePanel, etc.) are often more robust and better typed than injection zones. Use injection zones when you need to insert components into specific UI areas not covered by the Content Manager APIs.

内容管理器 API 和注入区都是用于自定义管理面板的扩展点,但它们解决的是不同的需求:

🌐 Content Manager APIs and injection zones are both extension points to customize the admin panel, but they solve different needs:

需求推荐的 API原因
在编辑视图侧边区域添加自定义面板内容管理器 API (addEditViewSidePanel)最适合在编辑时保持可见的上下文信息或控制。
在文档操作菜单中添加操作内容管理器 API (addDocumentAction)最适合在编辑视图操作菜单中执行文档级操作。
在编辑视图标题中添加操作内容管理器 API (addDocumentHeaderAction)最适合在文档标题旁进行快速、显眼的操作。
为列表视图中选定的条目添加操作内容管理器 API (addBulkAction)最适合用于同时应用于多个条目的工作流程。
在插件视图的预定义区域添加 UI(本地化视觉定制)注入区域 API (injectComponent)当你针对插件公开的特定区域时效果最佳。

有关实现细节和最新的 API 签名,请参阅 Strapi 代码库中的 content-manager 文件。

迷你示例(在 bootstrap(app) 内)

// Document action menu item
app.getPlugin('content-manager').apis.addDocumentAction(() => ({
label: 'Run custom action',
onClick: ({ documentId }) => runCustomAction(documentId),
}));

// Edit View header action
app.getPlugin('content-manager').apis.addDocumentHeaderAction(() => ({
label: 'Open preview',
onClick: ({ document }) => openPreview(document),
}));

// List View bulk action
app.getPlugin('content-manager').apis.addBulkAction(() => ({
label: 'Bulk publish',
onClick: ({ documentIds }) => bulkPublish(documentIds),
}));

// Edit View side panel
app.getPlugin('content-manager').apis.addEditViewSidePanel([
{
name: 'my-plugin.side-panel',
Component: MySidePanel,
},
]);

// Injection zone (plugin-defined zone)
app.getPlugin('content-manager').injectComponent('editView', 'right-links', {
name: 'my-plugin.custom-link',
Component: MyCustomLink,
});

预定义注入区

🌐 Predefined injection zones

Strapi 的内容管理器提供了插件可以使用的预定义注入区域:

🌐 Strapi's Content Manager provides predefined injection zones that plugins can use: | 视图 | 注入区域 | 位置 ||---|---|---|| 列表视图 | listView.actions | 过滤器和齿轮图标之间 || 列表视图 | listView.publishModalAdditionalInfos | 发布确认模态中的信息内容 || 列表视图 | listView.unpublishModalAdditionalInfos | 取消发布确认模态中的信息内容 || 列表视图 | listView.deleteModalAdditionalInfos | 删除确认模态中的信息内容 || 编辑视图 | editView.right-links | 在“配置视图”和“编辑”按钮之间 || 编辑视图 | editView.informations | 编辑视图的信息框内(内部,见下方备注) || 预览 | preview.actions | 在预览视图操作区域 |

listView.*ModalAdditionalInfos 区域旨在丰富发布、取消发布和删除确认模态框中显示的信息内容。

🌐 The listView.*ModalAdditionalInfos zones are intended to enrich the informational content displayed in publish, unpublish, and delete confirmation modals.

Caution

editView.informations 区域存在于内容管理器源代码中,但被视为内部区域。对于第三方插件,editView.right-links 是最稳定且官方推荐的编辑视图扩展点。只有在你特别需要信息面板区域并且可以接受不同版本间潜在的 UI 变化时,才使用 editView.informations

🌐 The editView.informations zone exists in the Content Manager source code but is considered internal. For third-party plugins, editView.right-links is the most stable and officially recommended Edit view extension point. Use editView.informations only when you specifically need the information panel area and accept potential UI changes between versions.

注入到内容管理器区域

🌐 Injecting into Content Manager zones

要将组件注入内容管理器注入区域,请在 bootstrap 生命周期中使用 getPlugin('content-manager').injectComponent()

🌐 To inject a component into a Content Manager injection zone, use getPlugin('content-manager').injectComponent() in the bootstrap lifecycle:

admin/src/index.js
import { MyCustomButton } from './components/MyCustomButton';
import { PreviewAction } from './components/PreviewAction';
import { PublishModalInfo } from './components/PublishModalInfo';

export default {
register(app) {
app.registerPlugin({
id: 'my-plugin',
name: 'My Plugin',
});
},
bootstrap(app) {
// Inject a button into the Edit view's right-links zone
app
.getPlugin('content-manager')
.injectComponent('editView', 'right-links', {
name: 'my-plugin-custom-button',
Component: MyCustomButton,
});

// Inject a component into the List view's actions zone
app
.getPlugin('content-manager')
.injectComponent('listView', 'actions', {
name: 'my-plugin-list-action',
Component: () => <button>Custom List Action</button>,
});

// Inject additional information into the publish modal
app
.getPlugin('content-manager')
.injectComponent('listView', 'publishModalAdditionalInfos', {
name: 'my-plugin-publish-modal-info',
Component: PublishModalInfo,
});

// Inject a component into the Preview view's actions zone
app
.getPlugin('content-manager')
.injectComponent('preview', 'actions', {
name: 'my-plugin-preview-action',
Component: PreviewAction,
});
},
};

自定义注入区域

🌐 Custom injection zones

插件可以定义自己的注入区域,以允许其他插件扩展它们的用户界面。在 registerPlugin 配置中声明注入区域:

🌐 Plugins can define their own injection zones to allow other plugins to extend their UI. Declare injection zones in the registerPlugin configuration:

admin/src/index.js
export default {
register(app) {
app.registerPlugin({
id: 'dashboard',
name: 'Dashboard',
injectionZones: {
homePage: {
top: [],
middle: [],
bottom: [],
},
sidebar: {
before: [],
after: [],
},
},
});
},
};

在组件中呈现注入区域

🌐 Rendering injection zones in components

在 Strapi 5 中,来自 @strapi/helper-pluginInjectionZone 组件已被移除,且没有直接的替代导出。要渲染注入的组件,请使用来自 @strapi/strapi/adminuseStrapiApp 创建你自己的组件。

🌐 In Strapi 5, the InjectionZone component from @strapi/helper-plugin is removed and has no direct replacement export. To render injected components, create your own component with useStrapiApp from @strapi/strapi/admin.

admin/src/components/CustomInjectionZone.jsx
import { useStrapiApp } from '@strapi/strapi/admin';

export const CustomInjectionZone = ({ area, ...props }) => {
const getPlugin = useStrapiApp('CustomInjectionZone', (state) => state.getPlugin);
const [pluginName, view, zone] = area.split('.');

const plugin = getPlugin(pluginName);
const components = plugin?.getInjectedComponents(view, zone);

if (!components?.length) {
return null;
}

return components.map(({ name, Component }) => <Component key={name} {...props} />);
};
admin/src/pages/Dashboard.jsx
import { CustomInjectionZone } from '../components/CustomInjectionZone';

const Dashboard = () => {
return (
<div>
<h1>Dashboard</h1>

{/* Render components injected into the top zone */}
<CustomInjectionZone area="dashboard.homePage.top" />

<div className="main-content">{/* Main dashboard content */}</div>

{/* Render components injected into the bottom zone */}
<CustomInjectionZone area="dashboard.homePage.bottom" />
</div>
);
};

export default Dashboard;

注入自定义区域

🌐 Injecting into custom zones

其他插件可以使用它们 bootstrap 生命周期中的 injectComponent() 方法将组件注入到你的自定义注入区域:

🌐 Other plugins can inject components into your custom injection zones using the injectComponent() method in their bootstrap lifecycle:

another-plugin/admin/src/index.js
import { Widget } from './components/Widget';

export default {
register(app) {
app.registerPlugin({
id: 'widget-plugin',
name: 'Widget Plugin',
});
},
bootstrap(app) {
const dashboardPlugin = app.getPlugin('dashboard');

if (dashboardPlugin) {
dashboardPlugin.injectComponent('homePage', 'top', {
name: 'widget-plugin-statistics',
Component: Widget,
});
}
},
};

喷射组件参数

🌐 Injection component parameters

injectComponent() 方法接受以下参数:

🌐 The injectComponent() method accepts the following parameters: | 参数 | 类型 | 描述 ||---|---|---|| view | string | 组件应该被注入的视图名称 || zone | string | 视图中组件应该被注入的区域名称 || component | object | 配置对象,包含 name(唯一字符串)和 Component(要注入的 React 组件) |

内容经理数据访问

🌐 Content Manager data access

在将组件注入内容管理器注入区域时,你可以使用 useContentManagerContext 钩子访问编辑视图数据:

🌐 When injecting components into Content Manager injection zones, you can access the Edit View data using the useContentManagerContext hook:

admin/src/components/MyCustomButton.jsx
import {
unstable_useContentManagerContext as useContentManagerContext,
} from '@strapi/strapi/admin';

export const MyCustomButton = () => {
const {
slug, // Content type slug (e.g., 'api::article.article')
model, // Content type model
id, // Document ID (undefined when creating)
collectionType, // 'single-types' or 'collection-types'
isCreatingEntry, // Whether creating a new entry
isSingleType, // Whether the content type is a single type
hasDraftAndPublish, // Whether draft & publish is enabled
contentType, // Content type schema
components, // Component schemas
layout, // Content type layout
form, // Form state and handlers
} = useContentManagerContext();

const { initialValues, values, onChange } = form;

const handleCustomAction = () => {
onChange({ target: { name: 'customField', value: 'new value' } });
};

return <button onClick={handleCustomAction}>Custom Action</button>;
};
Caution

useContentManagerContext 钩子目前以 unstable_useContentManagerContext 导出。unstable_ 前缀表示该 API 在未来版本中可能会发生变化。该钩子替代了来自 @strapi/helper-plugin 的已弃用 [useCMEditViewDataManager](/cms/migration/v4-to-v5/additional-resources/helper-plugin#usecmeditviewdatamanager),该钩子在 Strapi 5 中不可用。

🌐 The useContentManagerContext hook is currently exported as unstable_useContentManagerContext. The unstable_ prefix indicates the API may change in future releases. This hook replaces the deprecated useCMEditViewDataManager from @strapi/helper-plugin which is not available in Strapi 5.

最佳实践

🌐 Best practices

  • 使用描述性的区域名称。 为你的注入区域选择清晰的名称(例如,topbottombeforeafter)。

  • 检查插件可用性。 在将组件注入插件的区域之前,请始终确认该插件是否存在:

    bootstrap(app) {
    const targetPlugin = app.getPlugin('target-plugin');
    if (targetPlugin) {
    targetPlugin.injectComponent('view', 'zone', {
    name: 'my-component',
    Component: MyComponent,
    });
    }
    }
  • 使用唯一的组件名称。 确保组件名称是唯一的,以避免与其他插件发生冲突。

  • 优雅地处理缺失的区域。 组件应处理注入区域可能不可用的情况。

  • 记录你的注入区域。 清晰地记录你的插件提供了哪些注入区域以及它们的预期用途。