title: "上下文" post_status: publish comment_status: open taxonomy: category: - gutenberg-docs post_tag: - Block Api - Reference Guides - Repos


上下文

区块上下文是一项功能,它允许祖先区块提供值,供其自身层级结构内的后代区块使用。这些后代区块可以继承这些值,而无需依赖硬编码值,也无需明确知晓提供这些值的区块。

这在全站编辑中尤其有用,例如,区块的内容可能取决于显示它的文章上下文。一个博客滚动模板可能显示许多不同文章的摘要。通过使用区块上下文,仍然可以有一个单一的“文章摘要”区块,根据继承的文章 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: '记录标题',
    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

A block's context values are available from the context property of the $block argument passed as the third argument to the render_callback function.

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'];
    },
) );

Example

  1. Create a record block.
npm init @wordpress/block --namespace my-plugin record
cd record
  1. Edit src/index.js. Insert the recordId attribute and providesContext property in the registerBlockType function and add the registration of the record-title block at the bottom:
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. Edit src/edit.js for the record block. Replace the Edit function with the following code:
import { TextControl } from '@wordpress/components';
import { InnerBlocks } from '@wordpress/block-editor';

export default function Edit( props ) {
    const MY_TEMPLATE = [ [ 'my-plugin/record-title', {} ] ];
    const {
        attributes: { recordId },
        setAttributes,
    } = props;
    return (
        <div>
            <TextControl
                __next40pxDefaultSize
                label={ __( 'Record ID' ) }
                value={ recordId }
                onChange={ ( val ) =>
                    setAttributes( { recordId: Number( val ) } )
                }
            />
            <InnerBlocks template={ MY_TEMPLATE } templateLock="all" />
        </div>
    );
}
  1. Edit src/save.js for the record block. Replace the save function with the following code:
export default function save( props ) {
    return <p>The record ID: { props.attributes.recordId }</p>;
}
  1. Create a new post and add the record block. If you type a number in the text box, you'll see the same number is shown in the record-title block below it.

Block Context Example