本页面提供了关于弃用 API 的原则和使用方法的综合指南。入门介绍请查看在开发者博客上找到的块弃用基础教程。

在更新静态块的标记和属性时,块作者需要考虑使用旧版块的现有文章。为了提供良好的升级路径,您可以选择以下策略之一:

  • 不弃用该块并创建一个新块(不同的名称)
  • 提供“已弃用”版本的块,允许用户在块编辑器中打开这些块并使用更新的块进行编辑。

一个块可以有多个已弃用的版本。如果解析后的块的当前状态无效,或者弃用定义了返回 true 的 isEligible 函数,则尝试该弃用。

弃用不像其他软件数据更新(如数据库迁移)那样作为一系列更新运行。乍一看,很容易认为每个弃用都会对数据进行所需的更改,然后将这种新形式的块传递给下一个弃用以进行其更改。实际发生的是:

  1. 如果当前的 save 方法不生成有效的块,则弃用数组中的第一个弃用将接收原始保存的内容。
  2. 如果其 save 方法生成有效内容,则使用该弃用来解析块属性。如果它有 migrate 方法,也将使用弃用解析的属性运行它。
  3. 如果第一个弃用的 save 方法不生成有效的块,则尝试数组中的后续弃用,直到遇到一个生成有效块的弃用为止。
  4. 然后将从第一个弃用来生成有效块的属性和任何 innerBlocks 返回给当前的 save 方法,以生成块的新有效内容。
  5. 此时,当前块应处于有效状态,弃用工作流停止。

重要的是要注意,如果弃用的 save 方法不生成有效的块,则完全跳过它,包括其 migrate 方法,即使 isEligible 对于给定的属性返回 true。这意味着如果您为块有多个弃用并希望执行新迁移(例如将内容移动到 InnerBlocks),您可能需要更新多个弃用中的 migrate 方法,以便对块的所有先前版本应用所需的更改。

同样重要的是要注意,如果弃用的 save 方法从其他文件导入额外函数,对这些文件的更改可能会意外改变弃用的行为。您可能希望将这些函数的快照副本添加到弃用文件中,而不是导入它们,以避免无意中破坏弃用。

对于具有多个弃用的块,将每个弃用保存到适用于该块版本的常量中可能更容易,然后将这些添加到块的 deprecated 数组中。数组中的弃用应按逆时间顺序排列。这允许块编辑器尝试首先应用最新和最可能的弃用,避免不必要的和昂贵的处理。

示例

const v1 = {};
const v2 = {};
const v3 = {};
const deprecated = [ v3, v2, v1 ];

还建议保留包含块内容的不同版本的fixtures,以便您可以轻松测试新的弃用和迁移是否在所有先前版本的块上有效。

弃用在块类型上定义为其 deprecated 属性,这是一个弃用对象数组,其中每个对象采用以下形式:

  • attributes (Object):弃用形式的块的属性定义。
  • supports (Object):弃用形式的块的支持定义。
  • save (Function):弃用形式的块的保存实现。
  • migrate: (Function, Optional)。一个函数,给定旧属性和 innerBlocks 预期返回新属性或与块兼容的属性和 innerBlocks 元组数组。如上所述,如果弃用的 save 函数不返回有效块,则不会运行其 migrate,因此您需要确保在相关的弃用中提供迁移。
    • 参数
      • attributes:块的旧属性。
      • innerBlocks:块的旧 innerBlocks。
    • 返回
      • Object | Array:更新的块属性或元组数组 [attributes, innerBlocks]。
  • isEligible: (Function, Optional)。一个函数,如果弃用可以处理块迁移(即使块有效)则返回 true。它在块在技术上已弃用但仍需要更新其属性或 innerBlocks 的情况下特别有用。当所有先前弃用的保存函数的结果无效时不会调用此函数。
    • 参数
      • attributes:从序列化 HTML 解析的原始块属性,在应用块类型代码之前。
      • innerBlocks:块的当前 innerBlocks。
      • data:包含表示块节点及其生成的块对象的属性的对象。
        • data.blockNode:解析序列化 HTML 后的块的原始形式。
        • data.block:块对象,即将块类型应用于 blockNode 的结果。
    • 返回
      • boolean:此其他有效块是否由该弃用迁移。
重要的是要注意,attributes、supports 和 save 不会自动从当前版本继承,因为它们会影响块的解析和序列化,因此必须在弃用对象中定义它们以便在迁移期间处理。

示例

const { registerBlockType } = wp.blocks;
const attributes = {
    text: {
        type: 'string',
        default: 'some random value',
    },
};
const supports = {
    className: false,
};

registerBlockType( 'gutenberg/block-with-deprecated-version', {
    // ... other block properties go here

    attributes,

    supports,

    save( props ) {
        return <div>{ props.attributes.text }</div>;
    },

    deprecated: [
        {
            attributes,

            supports,

            save( props ) {
                return <p>{ props.attributes.text }</p>;
            },
        },
    ],
} );

在上面的示例中,我们更新了块的标记以使用 div 而不是 p。

更改属性集

有时,您需要更新属性集以重命名或修改旧属性。

示例

const { registerBlockType } = wp.blocks;

registerBlockType( 'gutenberg/block-with-deprecated-version', {
    // ... other block properties go here

    attributes: {
        content: {
            type: 'string',
            default: 'some random value',
        },
    },

    save( props ) {
        return <div>{ props.attributes.content }</div>;
    },

    deprecated: [
        {
            attributes: {
                text: {
                    type: 'string',
                    default: 'some random value',
                },
            },

            migrate( { text } ) {
                return {
                    content: text,
                };
            },

            save( props ) {
                return <p>{ props.attributes.text }</p>;
            },
        },
    ],
} );

在上面的示例中,我们更新了块的标记以使用 div 而不是 p,并将 text 属性重命名为 content。

更改 innerBlocks

在某些情况下,迁移块时可能需要添加或删除 innerBlocks。
例如:一个块希望将标题属性迁移到段落 innerBlocks。

示例

const { registerBlockType } = wp.blocks;

registerBlockType( 'gutenberg/block-with-deprecated-version', {
    // ... block properties go here

    save( props ) {
        return <p>{ props.attributes.title }</p>;
    },

    deprecated: [
        {
            attributes: {
                title: {
                    type: 'string',
                    source: 'html',
                    selector: 'p',
                },
            },

            migrate( attributes, innerBlocks ) {
                const { title, ...restAttributes } = attributes;

                return [
                    restAttributes,
                    [
                        createBlock( 'core/paragraph', {
                            content: attributes.title,
                            fontSize: 'large',
                        } ),
                        ...innerBlocks,
                    ],
                ];
            },

            save( props ) {
                return <p>{ props.attributes.title }</p>;
            },
        },
    ],
} );

在上面的示例中,我们更新了该块,使其使用带有标题的内联段落块,而不是标题属性。

以上是块弃用的示例案例。对于更多真实世界的示例,请检查 核心块库 中的弃用情况。核心块已随版本更新,并包含简单和复杂的弃用。