gutenbergdocs/docs/how-to-guides/block-tutorial/creating-dynamic-blocks.md
2025-10-22 01:40:18 +08:00

137 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 创建动态区块
动态区块是在前端渲染时实时构建结构和内容的区块。
动态区块主要有两个用途:
1. **内容需要实时更新的区块**即使文章未更新区块内容也会自动变化。WordPress 自带的「最新文章」区块就是典型示例——每当发布新文章时,所有使用该区块的位置都会同步更新。
2. **需要即时呈现代码更新的区块**当修改区块代码HTML/CSS/JS使用动态区块可确保修改立即在全站所有该区块实例上生效。若不使用动态区块Gutenberg 的[验证流程](/docs/reference-guides/block-api/block-edit-save.md#validation)会触发,导致用户看到“此区块似乎已被外部修改”的提示)
对于多数动态区块,`save` 回调函数应返回 `null`,这会让编辑器仅将[区块属性](/docs/reference-guides/block-api/block-attributes.md)保存至数据库。这些属性随后会传入服务端渲染回调,从而由开发者决定如何在前端展示区块。返回 `null` 时,编辑器会跳过区块标记验证流程,避免因频繁变化的标记引发问题。
若在动态区块中使用 [InnerBlocks](/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md),需通过 `<InnerBlocks.Content/>``save` 回调中保存内部区块内容。
也可保存区块的 HTML 表示形式。若设置了服务端渲染回调,该 HTML 会被回调输出替换;但当区块被停用或渲染回调被移除时,此 HTML 仍会正常渲染。
区块属性可用于保存任何需要存储的内容或设置。例如最新文章区块中,可将要显示的文章数量保存为属性;又或者针对需要在前端展示的每项内容(如标题文本、段落文字、图片、链接等),都可通过属性进行配置。
以下代码示例展示了如何创建仅显示最新文章链接的动态区块:
```jsx
import { registerBlockType } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import { useBlockProps } from '@wordpress/block-editor';
registerBlockType( 'gutenberg-examples/example-dynamic', {
apiVersion: 3,
title: '示例:最新文章',
icon: 'megaphone',
category: 'widgets',
edit: () => {
const blockProps = useBlockProps();
const posts = useSelect( ( select ) => {
return select( 'core' ).getEntityRecords( 'postType', 'post' );
}, [] );
return (
<div { ...blockProps }>
{ ! posts && '加载中' }
{ posts && posts.length === 0 && '暂无文章' }
{ posts && posts.length > 0 && (
<a href={ posts[ 0 ].link }>
{ posts[ 0 ].title.rendered }
</a>
) }
</div>
);
},
} );
```
由于是动态区块,无需在客户端重写默认的 `save` 实现,但需要配置服务端组件。前端显示内容取决于 `register_block_type``render_callback` 属性所调用的函数。
```php
<?php
/**
* 插件名称Gutenberg 动态区块示例
*/
function gutenberg_examples_dynamic_render_callback( $block_attributes, $content ) {
$recent_posts = wp_get_recent_posts( array(
'numberposts' => 1,
'post_status' => 'publish',
) );
if ( count( $recent_posts ) === 0 ) {
return '暂无文章';
}
$post = $recent_posts[ 0 ];
$post_id = $post['ID'];
return sprintf(
'<a class="wp-block-my-plugin-latest-post" href="%1$s">%2$s</a>',
esc_url( get_permalink( $post_id ) ),
esc_html( get_the_title( $post_id ) )
);
}
function gutenberg_examples_dynamic() {
// 自动加载依赖项与版本号
$asset_file = include( plugin_dir_path( __FILE__ ) . 'build/index.asset.php');
wp_register_script(
'gutenberg-examples-dynamic',
plugins_url( 'build/block.js', __FILE__ ),
$asset_file['dependencies'],
$asset_file['version']
);
register_block_type( 'gutenberg-examples/example-dynamic', array(
'api_version' => 3,
'editor_script' => 'gutenberg-examples-dynamic',
'render_callback' => 'gutenberg_examples_dynamic_render_callback'
) );
}
add_action( 'init', 'gutenberg_examples_dynamic' );
```
需要注意以下几点:
- `edit` 函数仍在编辑器中展示区块预览(可与渲染版本完全不同,由区块作者决定)
- 内置 `save` 函数直接返回 `null`,因为渲染在服务端完成
- 服务端渲染函数接收区块属性及内部内容作为参数,返回标记(与短代码机制高度相似)
**注意:** 关于颜色、边框、间距等常见自定义设置,我们将在[下一章](/docs/how-to-guides/block-tutorial/block-supports-in-dynamic-blocks.md)了解如何通过区块支持功能高效实现。
## 在区块编辑器中实时渲染
Gutenberg 2.8 版本引入了 [`<ServerSideRender>`](/packages/server-side-render/README.md) 区块,支持在服务端使用 PHP 进行渲染而非 JavaScript。
*服务端渲染仅作为降级方案,始终推荐使用客户端 JavaScript 渲染(速度更快且支持更灵活的编辑器操作)。*
```jsx
import { registerBlockType } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';
import { useBlockProps } from '@wordpress/block-editor';
registerBlockType( 'gutenberg-examples/example-dynamic', {
apiVersion: 3,
title: '示例:最新文章',
icon: 'megaphone',
category: 'widgets',
edit: function ( props ) {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<ServerSideRender
block="gutenberg-examples/example-dynamic"
attributes={ props.attributes }
/>
</div>
);
},
} );
```
注意此代码使用了 `wp-server-side-render` 包但未使用 `wp-data`,请确保在 PHP 代码中更新依赖项。建议使用 wp-scripts 自动构建依赖(具体 PHP 代码配置可参考 [block-development-examples 代码库](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/basic-esnext-a2ab62))。