title: "创建动态区块" post_status: publish comment_status: open taxonomy: category: - gutenberg-docs post_tag: - Block Tutorial - How To Guides - Repos
创建动态区块
动态区块是在前端渲染时实时构建其结构和内容的区块。
动态区块主要有两种用途:
- 即使文章未更新,内容也应发生变化的区块。WordPress 自身的"最新文章"区块就是一个例子。当有新文章发布时,该区块在所有使用它的地方都会更新。
- 代码(HTML、CSS、JS)的更新应立即在网站前端显示的区块。例如,如果您通过添加新类、添加 HTML 元素或以任何其他方式更改布局来更新区块结构,使用动态区块可确保这些更改立即应用于整个网站中该区块的所有实例。(如果不使用动态区块,当区块代码更新时,通常会应用 Gutenberg 的验证过程,导致用户看到验证消息"此区块似乎已被外部修改")。
对于许多动态区块,save 回调函数应返回 null,这告诉编辑器仅将区块属性保存到数据库。然后这些属性会传递到服务器端渲染回调中,因此您可以决定如何在网站前端显示该区块。当您返回 null 时,编辑器将跳过区块标记验证过程,避免因频繁更改标记而产生问题。
如果您在动态区块中使用 InnerBlocks,则需要在 save 回调函数中使用 <InnerBlocks.Content/> 保存 InnerBlocks。
您也可以保存区块的 HTML 表示形式。如果您提供了服务器端渲染回调,此 HTML 将被回调的输出替换,但如果您的区块被停用或渲染回调被移除,则会渲染此 HTML。
区块属性可用于您想要为该区块保存的任何内容或设置。在上面的第一个示例中,对于最新文章区块,您想要显示的最新文章数量可以保存为属性。或者在第二个示例中,属性可用于您想要在前端显示的每个内容片段——例如标题文本、段落文本、图像、URL 等。
以下代码示例展示了如何创建一个仅显示最新文章链接的动态区块。
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 && 'Loading' }
{ posts && posts.length === 0 && 'No Posts' }
{ posts && posts.length > 0 && (
<a href={ posts[ 0 ].link }>
{ posts[ 0 ].title.rendered }
</a>
) }
</div>
);
},
} );
Because it is a dynamic block it doesn't need to override the default `save` implementation on the client. Instead, it needs a server component. The contents in the front of your site depend on the function called by the `render_callback` property of `register_block_type`.
```php
<?php
/**
* Plugin Name: Gutenberg examples dynamic
*/
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 'No posts';
}
$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() {
// automatically load dependencies and version
$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' );
There are a few things to notice:
- The
editfunction still shows a representation of the block in the editor's context (this could be very different from the rendered version, it's up to the block's author) - The built-in
savefunction just returnsnullbecause the rendering is performed server-side. - The server-side rendering is a function taking the block and the block inner content as arguments, and returning the markup (quite similar to shortcodes)
Note : For common customization settings including color, border, spacing customization and more, we will see on the next chapter how you can rely on block supports to provide such functionality in an efficient way.
Live rendering in the block editor
Gutenberg 2.8 added the <ServerSideRender> block which enables rendering to take place on the server using PHP rather than in JavaScript.
Server-side render is meant as a fallback; client-side rendering in JavaScript is always preferred (client rendering is faster and allows better editor manipulation).
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: 'Example: last post',
icon: 'megaphone',
category: 'widgets',
edit: function ( props ) {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<ServerSideRender
block="gutenberg-examples/example-dynamic"
attributes={ props.attributes }
/>
</div>
);
},
} );
Note that this code uses the wp-server-side-render package but not wp-data. Make sure to update the dependencies in the PHP code. You can use wp-scripts to automatically build dependencies (see the block-development-examples repo for PHP code setup).