动态块是在前端渲染该块时即时构建其结构和内容的块。
动态块主要有两种用途:
- 即使文章未更新,内容也应发生变化的块。WordPress 自身的一个示例是“最新文章”块。当发布新文章时,此块会在所有使用位置进行更新。
- 代码(HTML、CSS、JS)的更新应立即可在网站的页面上显示的块。例如,如果您通过添加新类、添加 HTML 元素或以其他方式更改布局来更新块的结构,使用动态块可确保这些更改立即应用于站点上该块的所有实例。(如果不使用动态块,则当块代码更新时,Gutenberg 的 验证流程通常会适用,导致用户看到验证消息“此块似乎已被外部修改”)。
对于许多动态块,应返回 save 回调函数为 null,这指示编辑器仅将 块属性保存到数据库。然后将这些属性传递给服务器端渲染回调,因此您可以决定如何在站点的前端显示该块。当您返回 null 时,编辑器将跳过块标记验证流程,避免与频繁更改的标记相关的问题。
如果您在动态块中使用 InnerBlocks,则需要在 save 回调函数中保存 InnerBlocks,使用 <InnerBlocks.Content/>
您还可以保存块的 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: 'Example: last post',
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>
);
},
} );
由于它是动态块,因此不需要覆盖客户端上的默认 save 实现。相反,它需要一个服务器端组件。您站点前端的內容取决于 register_block_type 的 render_callback 属性调用的函数。
<?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' );
有几点需要注意:
edit函数仍然在编辑器的上下文中显示块的表示形式(这可能非常不同于渲染版本,这取决于块的作者)- 内置的
save函数仅返回null,因为渲染是在服务器端执行的。 - 服务器端渲染是一个接受块和块内部内容作为参数并返回标记的函数(与短代码非常相似)
注意:对于常见的自定义设置,包括颜色、边框、间距自定义等,您可以依靠 块支持 以高效方式提供此类功能。
块编辑器中的实时渲染
Gutenberg 2.8 添加了 <ServerSideRender> 块,它启用使用 PHP 而不是 JavaScript 在服务器上进行渲染。
服务器端渲染旨在作为回退;JavaScript 中的客户端渲染始终首选(客户端渲染速度更快并允许更好的编辑器操作)。
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>
);
},
} );
请注意,此代码使用 wp-server-side-render 包但不使用 wp-data。请确保更新 PHP 代码中的依赖项。您可以使用 wp-scripts 自动构建依赖项(有关 PHP 代码设置,请参阅 block-development-examples repo)。