块上下文(Block context)是一项功能,允许祖先块在其自身的层级结构中为后代块提供可被消费的值。这些后代块可以继承这些值,而无需使用硬编码的值,也无需显式了解提供这些值的块。

这在全站编辑中特别有用,例如,块的内容可能取决于其显示所在的帖子的上下文。博客目录模板可能会显示许多不同帖子的摘要。使用块上下文,仍然可以有一个单一的“帖子摘要”块,该块基于继承的帖子 ID 来显示帖子的内容。

如果您熟悉 React Context,则块上下文采用了许多相同的理念。事实上,客户端块编辑器中的块上下文实现是 React Context 的一个非常简单应用。块上下文也支持服务器端 render_callback 实现,如下面的示例所示。

定义块上下文

块上下文在块的注册设置中定义。一个块可以提供上下文值,或消费其寻求继承的值。

提供块上下文

块可以通过在其注册设置中分配 providesContext 属性来提供上下文值。这是一个将上下文名称映射到块自身属性的对象。与该属性值对应的值可供后代块使用,并且可以使用相同的上下文名称引用它。目前,块上下文仅支持源自块自身属性的值。这可以在未来增强以支持额外的上下文值来源。

    attributes: {
        recordId: {
            type: 'number',
        },
    },

    providesContext: {
        'my-plugin/recordId': 'recordId',
    },

完整示例请参考下面部分。

包含命名空间

如上例所示,建议在上下文键名称中包含命名空间,以避免与其他插件或 WordPress 提供的默认上下文值发生潜在冲突。上下文命名空间应特定于您的插件,并且在大多数情况下可以与块本身使用的名称相同。

消费块上下文

块可以通过在其注册设置中分配 usesContext 属性从祖先提供者继承上下文值。这应作为块寻求继承的上下文名称数组进行分配。

registerBlockType('my-plugin/record-title', {
    title: 'Record Title',
    category: 'widgets',

    usesContext: ['my-plugin/recordId'],

使用块上下文

一旦块定义了其寻求继承的上下文,就可以在 edit(JavaScript)和 render_callback(PHP)的实现中访问它。它作为对象(JavaScript)或关联数组(PHP)提供,其中包含为块定义的上下文值。请注意,只有当块明确定义了对该值的继承欲望时,上下文值才会可用。

注意:块上下文不适用于 save。

JavaScript

registerBlockType('my-plugin/record-title', {

    edit({ context }) {
        return 'The record ID: ' + context['my-plugin/recordId'];
    },

PHP

块的上下文值可以从 $block 参数的 context 属性中获取,该参数作为第三个参数传递给 render_callback 函数。

register_block_type( 'my-plugin/record-title', array(
    'render_callback' => function( $attributes, $content, $block ) {
        return 'The current record ID is: ' . $block->context['my-plugin/recordId'];
    },
) );

示例

  1. 创建一个 record 块。
npm init @wordpress/block --namespace my-plugin record
cd record
  1. 编辑 src/index.js。在 registerBlockType 函数中插入 recordId 属性和 providesContext 属性,并在底部添加 record-title 块的注册:
registerBlockType( 'my-plugin/record', {
    // ... cut ...

    attributes: {
        recordId: {
            type: 'number',
        },
    },

    providesContext: {
        'my-plugin/recordId': 'recordId',
    },

    /**
     * @see ./edit.js
     */
    edit: Edit,

    /**
     * @see ./save.js
     */
    save,
} );

registerBlockType( 'my-plugin/record-title', {
    title: 'Record Title',
    category: 'widgets',

    usesContext: [ 'my-plugin/recordId' ],

    edit( { context } ) {
        return 'The record ID: ' + context[ 'my-plugin/recordId' ];
    },

    save() {
        return null;
    },
} );
  1. 编辑 src/edit.js 中的 record 块。用以下代码替换 Edit 函数:
import { TextControl } from '@wordpress/components';
import { InnerBlocks } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

export default function Edit( props ) {
    const MY_TEMPLATE = [ [ 'my-plugin/record-title', {} ] ];
    const {
        attributes: { recordId },
        setAttributes,
    } = props;
    return (
        <div>
            <TextControl
                label={ __( 'Record ID' ) }
                value={ recordId }
                onChange={ ( val ) =>
                    setAttributes( { recordId: Number( val ) } )
                }
            />
            <InnerBlocks template={ MY_TEMPLATE } templateLock="all" />
        </div>
    );
}
  1. 编辑 src/save.js 中的 record 块。用以下代码替换 save 函数:
export default function save( props ) {
    return <p>The record ID: { props.attributes.recordId }</p>;
}
  1. 创建一篇新帖子并添加 record 块。如果您在文本框中输入数字,您将在其下方的 record-title 块中看到相同的数字。

块上下文示例