gutenbergdocs/docs/getting-started/fundamentals/static-dynamic-rendering.md
2025-10-22 01:40:18 +08:00

12 KiB
Raw Blame History

数据库中动态区块的HTML呈现方式save方法)

对于动态区块,save回调函数可以直接返回null,这将告知编辑器仅将区块分隔注释(以及现有的区块属性)保存至数据库。这些属性随后会被传递到服务端渲染回调函数,由该函数决定如何在前端站点上显示区块。

save返回null时,区块编辑器将跳过区块标记验证流程,避免因频繁变化的标记引发问题。

具有动态渲染功能的区块也可以保存区块的HTML表示作为备用方案。如果您提供了服务端渲染回调数据库中代表区块的HTML将被回调输出所替代但若区块被停用注册区块的插件被卸载或渲染回调被移除则会呈现原保存的HTML。

在某些情况下区块会保存其HTML表示并在满足特定条件时使用动态渲染来优化标记。核心区块中使用此方法的示例包括

如果在动态区块中使用内部区块,您需要通过<InnerBlocks.Content/>save回调函数中保存InnerBlocks

扩展资源

区块的静态与动态渲染

区块的前端标记既可以在请求时由服务器端动态生成(动态区块),也可以在区块编辑器的保存过程中静态生成(静态区块)。本文将深入探讨这两种实现方式。

《静态区块与动态区块:差异解析》这篇技术文章为本主题提供了绝佳的入门指引。

静态渲染

采用"静态渲染"的区块在保存时就会生成固定不变的前端输出并存储至数据库。这类区块完全依赖其 save 函数来定义其 HTML 标记结构,除非在区块编辑器中进行手动修改,否则这些标记将始终保持不变。

若某个区块未采用动态渲染方式——即不通过 PHP 在页面加载时实时生成内容——则会被归类为"静态区块"。

下图直观展示了静态区块内容如何保存至数据库,并在前端被检索并渲染为 HTML 的过程。

静态渲染区块示意图

如何为区块定义静态渲染

通过在客户端注册区块时可定义的 save 函数,可以指定区块的 HTML 结构。每当在编辑器中保存区块时,该 HTML 结构就会被存入数据库,并最终用于前端展示。

WordPress 中的区块会被封装在特殊的注释标签内,这些标签作为唯一的区块定界符存在。但最终渲染时,只会呈现静态区块 save 函数中定义的 HTML 内容(不包含这些定界符)。

查看预格式化区块中的静态渲染示例
以下是 预格式化 核心区块的 save 函数示例:
import { RichText, useBlockProps } from '@wordpress/block-editor';

export default function save( { attributes } ) {
	const { content } = attributes;

	return (
		<pre { ...useBlockProps.save() }>
			<RichText.Content value={ content } />
		</pre>
	);
}

attributes.content 的值为 "这是一段预格式化文本" 时,该函数会生成如下区块标记表示:

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">这是一段预格式化文本</pre>
<!-- /wp:preformatted -->

在前端,该区块将返回以下标记。请注意定界符已不复存在。

<pre class="wp-block-preformatted">这是一段预格式化文本</pre>

我们将在下一节探讨的动态区块,虽然也能通过 save 函数指定初始 HTML 结构(类似于静态区块),但它们主要依赖服务器端渲染来生成内容。如果因故无法进行动态渲染(比如区块插件被停用),系统将转而使用数据库中保存的 HTML 结构来在前端显示该区块。

要了解具体运作机制,请参阅构建你的第一个区块教程。特别是添加静态渲染章节,生动演示了区块如何同时具备保存 HTML 结构和动态渲染能力。

WordPress 提供了诸如 render_blockrender_callback 等机制,用于在区块最终呈现到前端之前修改其保存的 HTML。这些工具赋予开发者动态定制区块输出的能力以满足复杂交互场景的需求。

更多采用静态渲染的 WordPress 区块示例(即其输出在保存时即固定,不依赖服务器端处理)包括:

动态渲染

具备“动态渲染”功能的区块旨在前端请求时实时生成其内容和结构。与在数据库中保存固定HTML结构的静态区块不同“动态区块”依赖服务器端处理来动态构建输出这使其具有高度灵活性非常适合需要频繁更新或依赖外部数据的内容。

下图展示了动态区块的表示形式如何在数据库中保存然后在前端检索并动态渲染为HTML。

动态渲染区块示意图

动态区块的常见应用场景包括:

  1. 内容需在文章未更新时自动变化的区块:例如最新文章区块,每当有新文章发布时会自动更新。
  2. 标记更新需立即在前端显示的区块若通过添加新类、HTML元素或任何方式更新区块结构使用动态区块可确保这些更改立即应用到全站所有该区块实例。若无动态区块类似更新可能触发区块编辑器中的验证错误

如何为区块定义动态渲染

区块可通过两种主要方式定义动态渲染:

  1. 使用可传递给register_block_type()函数的render_callback参数。这对于纯PHP区块是必需的。
  2. 使用通常命名为render.php的独立PHP文件。该文件路径应在block.json文件中通过render属性定义。

这两种方法都会接收以下数据:

  • $attributes:区块的属性数组。
  • $content:数据库中存储的区块标记(如有)。
  • $block:表示已渲染区块的WP_Block类实例(区块元数据)。
查看站点标题区块中的动态渲染示例

站点标题区块使用以下render_callback

function render_block_core_site_title( $attributes ) {
	$site_title = get_bloginfo( 'name' );
	if ( ! $site_title ) {
		return;
	}

	$tag_name = 'h1';
	$classes  = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}";
	if ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) {
		$classes .= ' has-link-color';
	}

	if ( isset( $attributes['level'] ) ) {
		$tag_name = 0 === $attributes['level'] ? 'p' : 'h' . (int) $attributes['level'];
	}

	if ( $attributes['isLink'] ) {
		$aria_current = is_home() || ( is_front_page() && 'page' === get_option( 'show_on_front' ) ) ? ' aria-current="page"' : '';
		$link_target  = ! empty( $attributes['linkTarget'] ) ? $attributes['linkTarget'] : '_self';

		$site_title = sprintf(
			'<a href="%1$s" target="%2$s" rel="home"%3$s>%4$s</a>',
			esc_url( home_url() ),
			esc_attr( $link_target ),
			$aria_current,
			esc_html( $site_title )
		);
	}
	$wrapper_attributes = get_block_wrapper_attributes( array( 'class' => trim( $classes ) ) );

	return sprintf(
		'<%1$s %2$s>%3$s</%1$s>',
		$tag_name,
		$wrapper_attributes,
		// 如果是链接则已预转义
		$attributes['isLink'] ? $site_title : esc_html( $site_title )
	);
}

但该区块未定义save函数,从其index.js文件可见,这意味着区块在数据库中的标记表示如下:

<!-- wp:site-title /-->

在前端,render_callback会根据请求区块时服务器的具体值动态渲染区块标记。这些值包括当前站点标题、URL、链接目标等。

<h1 class="wp-block-site-title"><a href="https://www.wp.org" target="_self" rel="home">我的WordPress网站</a></h1>