# 弃用

> 本页提供了关于弃用 API 原则和使用的完整指南。入门教程请查看[开发者博客](https://developer.wordpress.org/news/)上的[区块弃用基础教程](https://developer.wordpress.org/news/2023/03/block-deprecation-a-tutorial/)。

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

-   不弃用区块，而是创建一个新区块（使用不同的名称）
-   提供区块的"弃用"版本，允许用户在区块编辑器中打开这些区块时使用更新后的区块进行编辑。

一个区块可以有多个弃用版本。当解析后的区块当前状态无效，或者弃用定义了返回 true 的 `isEligible` 函数时，将尝试使用弃用版本。

弃用操作不像其他软件数据更新（如数据库迁移）那样以更新链的方式运行。乍一看，很容易认为每个弃用都会对数据进行必要的更改，然后将这种新形式的区块传递给下一个弃用以进行其更改。但实际上发生的是：

1. 如果当前的 `save` 方法无法生成有效区块，弃用数组中的第一个弃用将接收原始保存内容。
2. 如果其 `save` 方法生成有效内容，则使用此弃用来解析区块属性。如果它有 `migrate` 方法，也将使用弃用解析的属性运行。
3. 如果第一个弃用的 `save` 方法无法生成有效区块，则尝试数组中的后续弃用，直到找到能生成有效区块的弃用。
4. 从第一个生成有效区块的弃用中获取属性和任何内部区块，然后传递回当前的 `save` 方法，为区块生成新的有效内容。
5. 此时当前区块应处于有效状态，弃用工作流程停止。

需要注意的是，如果弃用的 `save` 方法无法生成有效区块，则完全跳过该弃用，包括其 `migrate` 方法，即使 `isEligible` 对给定属性会返回 true。这意味着如果您为区块设置了多个弃用并希望执行新的迁移（如将内容移动到 `InnerBlocks`），可能需要更新多个弃用中的 `migrate` 方法，以便将所需更改应用到区块的所有先前版本。

同样需要注意的是，如果某个废弃版本的 `save` 方法从其他文件导入了额外函数，对这些文件的修改可能会意外改变该废弃版本的行为。为避免无意中破坏废弃功能，建议将这些函数的快照副本添加到废弃文件中，而不是直接导入。

对于包含多个废弃版本的区块，更简便的做法是将每个废弃版本保存为常量，并注明其适用的区块版本，然后将这些常量添加到区块的 `deprecated` 数组中。数组中的废弃版本应按时间倒序排列。这样区块编辑器就能优先尝试应用最新且最可能的废弃版本，避免不必要的高开销处理。

**示例**

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

同时建议保留包含不同版本区块内容的[测试固件](https://github.com/WordPress/gutenberg/blob/HEAD/test/integration/fixtures/blocks/README.md)，以便轻松测试新的废弃版本和迁移功能是否在所有历史版本中正常工作。

废弃版本在区块类型中通过 `deprecated` 属性定义，该属性是一个废弃对象数组，每个对象采用以下形式：

-   `attributes` (Object): The [attributes definition](/docs/reference-guides/block-api/block-attributes) of the deprecated form of the block.
-   `supports` (Object): The [supports definition](/docs/reference-guides/block-api/block-registration) of the deprecated form of the block.
-   `save` (Function): The [save implementation](/docs/reference-guides/block-api/block-edit-save) of the deprecated form of the block.
-   `migrate`: (Function, Optional). A function which, given the old attributes and inner blocks is expected to return either the new attributes or a tuple array of attributes and inner blocks compatible with the block. As mentioned above, a deprecation's `migrate` will not be run if its `save` function does not return a valid block so you will need to make sure your migrations are available in all the deprecations where they are relevant.
	- _Parameters_
		- `attributes`: The block's old attributes.
		- `innerBlocks`: The block's old inner blocks.
	- _Return_
		- `Object | Array`: Either the updated block attributes or tuple array `[attributes, innerBlocks]`.
-   `isEligible`: (Function, Optional). A function which returns `true` if the deprecation can handle the block migration even if the block is valid. It is particularly useful in cases where a block is technically valid even once deprecated, but still requires updates to its attributes or inner blocks. This function is **not** called when the results of all previous deprecations' save functions were invalid.
	- _Parameters_
		- `attributes`: The raw block attributes as parsed from the serialized HTML, and before the block type code is applied.
		- `innerBlocks`: The block's current inner blocks.
		- `data`: An object containing properties representing the block node and its resulting block object.
			- `data.blockNode`: The raw form of the block as a result of parsing the serialized HTML.
			- `data.block`: The block object, which is the result of applying the block type to the `blockNode`.
	- _Return_
		- `boolean`: Whether or not this otherwise valid block is eligible to be migrated by this deprecation.

<div class="callout callout-alert">
It's important to note that <code>attributes</code>, <code>supports</code>, and <code>save</code> are not automatically inherited from the current version, since they can impact parsing and serialization of a block, so they must be defined on the deprecated object in order to be processed during a migration.
</div>

**Example**

```js
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`。

## Changing the attributes set

Sometimes, you need to update the attributes set to rename or modify old attributes.

**Example**


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


In the example above we updated the markup of the block to use a `div` instead of `p` and rename the `text` attribute to `content`.

## Changing the innerBlocks

Situations may exist where when migrating the block we may need to add or remove innerBlocks.
E.g: a block wants to migrate a title attribute to a paragraph innerBlock.

**Example**

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

In the example above we updated the block to use an inner Paragraph block with a title instead of a title attribute.

_Above are example cases of block deprecation. For more, real-world examples, check for deprecations in the [core block library](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-library/src). Core blocks have been updated across releases and contain simple and complex deprecations._