gutenbergdocs/docs/reference-guides/slotfills/README.md
2025-10-22 01:40:18 +08:00

11 KiB
Raw Permalink Blame History

当前可用的 SlotFill 及示例

以下 SlotFill 可在 edit-posteditor 包中使用。具体用法及示例请参阅下列各项:

SlotFills 参考文档

Slot插槽与 Fill填充是已公开的组件允许开发者将项目注入到 Gutenberg 管理体验中的某些预定义位置。
更多详细信息请参阅 SlotFill 组件文档

要使用这些组件,我们必须利用 @wordpress/plugins API 注册一个用于注入项目的插件。

使用概览

使用 SlotFills 需要完成以下四个步骤:

  1. @wordpress/plugins 包导入 registerPlugin 方法
  2. @wordpress/editor 包导入所需的 SlotFill 组件
  3. 定义渲染内容的组件。需将修改/新增内容包裹在导入的 SlotFill 组件中
  4. 注册插件

以下是通过 PluginPostStatusInfo 插槽填充的示例:

import { registerPlugin } from '@wordpress/plugins';
import { PluginPostStatusInfo } from '@wordpress/editor';

const PluginPostStatusInfoTest = () => (
	<PluginPostStatusInfo>
		<p>文章状态信息插槽填充</p>
	</PluginPostStatusInfo>
);

registerPlugin( 'post-status-info-test', { render: PluginPostStatusInfoTest } );

条件化渲染 SlotFill 内容

MainDashboardButton 外,所有可用的 SlotFill 同时在文章编辑器和站点编辑器中公开,任何已注册的 Fill 都会在两种上下文中渲染。可通过多种方式实现条件化渲染。

限定填充内容至文章编辑器

通过检查当前文章类型对象的 viewable 属性是否为 true,可将填充内容限定在文章编辑器内。未设置为 viewable 的文章类型没有关联的文章编辑界面,这是判断用户不在文章编辑器中的有效依据。以下示例将在所有已注册文章类型的编辑界面中渲染内容:

/**
 * WordPress 依赖项
 */
import { registerPlugin } from '@wordpress/plugins';
import {
	PluginDocumentSettingPanel,
	store as editorStore,
} from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
 * 作为插件组成部分的渲染组件
 */
const EditPostDocumentSettingPanel = () => {
	// 获取当前文章类型信息
	const isViewable = useSelect( ( select ) => {
		const postTypeName = select( editorStore ).getCurrentPostType();
		const postTypeObject = select( coreStore ).getPostType( postTypeName );
		return postTypeObject?.viewable;
	}, [] );

	// 若文章类型不可查看,则不渲染填充内容
	if ( ! isViewable ) {
		return null;
	}

	return (
		<PluginDocumentSettingPanel
			name="custom-panel"
			title={ __( '文章编辑器示例' ) }
			className="custom-panel"
		>
			<p>{ __( '仅出现在文章编辑界面' ) }</p>
		</PluginDocumentSettingPanel>
	);
};

registerPlugin( 'example-post-edit-only', {
	render: EditPostDocumentSettingPanel,
} );

限定填充内容至特定文章类型

以下示例在前例基础上创建允许渲染的文章类型白名单。此处填充内容仅在编辑页面时渲染:

/**
 * WordPress 依赖项
 */
import { registerPlugin } from '@wordpress/plugins';
import {
	PluginDocumentSettingPanel,
	store as editorStore,
} from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';

/**
 * 作为插件组成部分的渲染组件
 */
const RestrictPostTypes = () => {
	// 获取当前文章类型信息
	const { isViewable, postTypeName } = useSelect( ( select ) => {
		const postType = select( editorStore ).getCurrentPostType();
		const postTypeObject = select( coreStore ).getPostType( postType );
		return {
			isViewable: postTypeObject?.viewable,
			postTypeName: postType,
		};
	}, [] );

	// 允许渲染插件的文章类型列表
	const allowedPostTypes = [ 'page' ];

	// 若文章类型不可查看或不在允许列表中,则不渲染插件
	if ( ! isViewable || ! allowedPostTypes.includes( postTypeName ) ) {
		return null;
	}

	return (
		<PluginDocumentSettingPanel
			name="custom-panel"
			title={ __( '文章类型限制示例' ) }
			className="custom-panel"
		>
			<p>
				{ sprintf(
					__(
						'仅出现在允许列表中的文章类型上。%s'
					),
					allowedPostTypes.join( ', ' )
				) }
			</p>
		</PluginDocumentSettingPanel>
	);
};

registerPlugin( 'example-restrict-post-types', {
	render: RestrictPostTypes,
} );

将填充内容限定在站点编辑器中显示

若要将填充内容限定在站点编辑器中显示,则需要采用反向逻辑。如果文章类型对象的 viewable 属性设置为 true,则不应渲染该填充内容。以下示例将在任意站点编辑器界面中渲染其内容。

/**
 * WordPress 依赖项
 */
import { registerPlugin } from '@wordpress/plugins';
import {
	PluginDocumentSettingPanel,
	store as editorStore,
} from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
 * 作为插件组成部分渲染的组件
 */
const SiteEditorDocumentSettingPanel = () => {
	// 获取当前文章类型信息
	const isViewable = useSelect( ( select ) => {
		const postTypeName = select( editorStore ).getCurrentPostType();
		const postTypeObject = select( coreStore ).getPostType( postTypeName );

		// 可查看的文章类型指能在 WordPress 后台查看的类型,内部类型不会设置为可查看
		return postTypeObject?.viewable;
	}, [] );

	// 若文章类型可查看,则不渲染填充内容
	if ( isViewable ) {
		return null;
	}

	return (
		<PluginDocumentSettingPanel
			name="custom-panel"
			title={ __( '站点编辑器示例' ) }
			className="custom-panel"
		>
			<p>{ __( '仅出现在站点编辑器中' ) }</p>
		</PluginDocumentSettingPanel>
	);
};

registerPlugin( 'example-site-editor', {
	render: SiteEditorDocumentSettingPanel,
} );

将填充内容限定在站点编辑器的特定界面中

此示例在前例基础上,通过提供允许列表来控制填充内容在站点编辑器中的显示界面。

/**
 * WordPress 依赖项
 */
import { registerPlugin } from '@wordpress/plugins';
import {
	PluginDocumentSettingPanel,
	store as editorStore,
} from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';

/**
 * 作为插件组成部分渲染的组件
 */
const SiteEditorDocumentSettingPanel = () => {
	// 站点编辑器中的允许区域
	const allowedSiteEditorScreens = [
		'wp_template', // 模板
		'wp_block', // 模式
		'wp_template_part', // 模板部件
	];

	const { isViewable, postType } = useSelect( ( select ) => {
		const postTypeName = select( editorStore ).getCurrentPostType();
		const postTypeObject = select( coreStore ).getPostType( postTypeName );

		return {
			// 可查看的文章类型指能在 WordPress 后台查看的类型,内部类型不会设置为可查看
			isViewable: postTypeObject?.viewable,
			postType: postTypeName,
		};
	}, [] );

	// 若文章类型可查看或不在允许列表中,则不渲染插件
	if ( isViewable || ! allowedSiteEditorScreens.includes( postType ) ) {
		return null;
	}

	return (
		<PluginDocumentSettingPanel
			name="custom-panel"
			title={ __( '仅限站点编辑器界面' ) }
			className="custom-panel"
		>
			<p>
				{ sprintf(
					__(
						'仅显示在允许列表中的编辑器界面。%s'
					),
					allowedSiteEditorScreens.join( '' )
				) }
			</p>
		</PluginDocumentSettingPanel>
	);
};

registerPlugin( 'example-site-editor-only', {
	render: SiteEditorDocumentSettingPanel,
} );

运作原理

SlotFill 通过 createSlotFill 创建。这会生成 SlotFill 两个组件,随后用于创建在 wp.plugins 全局变量上导出的新组件。

PluginPostStatusInfo SlotFill 的定义查看核心代码

/**
 * 定义摘要面板的可扩展性插槽
 */

/**
 * WordPress 依赖项
 */
import { createSlotFill, PanelRow } from '@wordpress/components';

export const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' );

const PluginPostStatusInfo = ( { children, className } ) => (
	<Fill>
		<PanelRow className={ className }>{ children }</PanelRow>
	</Fill>
);

PluginPostStatusInfo.Slot = Slot;

export default PluginPostStatusInfo;

这个新创建的 Slot 会在编辑器中暴露。以下示例来自核心代码,展示了摘要面板的实现。

可见 <PluginPostStatusInfo.Slot> 包裹了面板中所有要显示的项目。任何通过 SlotFill 添加的项目(参见前例)都会包含在 fills 参数中,并最终显示在组件末尾。

参见核心代码

export default function PostSummary( { onActionPerformed } ) {
	const { isRemovedPostStatusPanel } = useSelect( ( select ) => {
		// 使用 isEditorPanelRemoved 来在面板被程序化移除时隐藏它
		// 不使用 isEditorPanelEnabled 是因为此面板不应通过 UI 禁用
		const { isEditorPanelRemoved } = select( editorStore );
		return {
			isRemovedPostStatusPanel: isEditorPanelRemoved( PANEL_NAME ),
		};
	}, [] );

	return (
		<PostPanelSection className="editor-post-summary">
			<PluginPostStatusInfo.Slot>
				{ ( fills ) => (
					<>
						<VStack spacing={ 4 }>
							<PostCardPanel
								onActionPerformed={ onActionPerformed }
							/>
							<PostFeaturedImagePanel withPanelBody={ false } />
							<PostExcerptPanel />
							<VStack spacing={ 1 }>
								<PostContentInformation />
								<PostLastEditedPanel />
							</VStack>
							{ ! isRemovedPostStatusPanel && (
								<VStack spacing={ 2 }>
									<VStack spacing={ 1 }>
										<PostStatusPanel />
										<PostSchedulePanel />
										<PostURLPanel />
										<PostAuthorPanel />
										<PostTemplatePanel />
										<PostDiscussionPanel />
										<PageAttributesPanel />
										<PostSyncStatus />
										<BlogTitle />
										<PostsPerPage />
										<SiteDiscussion />
										<PostFormatPanel />
										<PostStickyPanel />
									</VStack>
									<TemplateAreas />
									{ fills }
								</VStack>
							) }
						</VStack>
					</>
				) }
			</PluginPostStatusInfo.Slot>
		</PostPanelSection>
	);
}