跳转到主要内容

区块的静态或动态渲染

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

文章 静态区块与动态区块:有何区别? 对此主题提供了很好的介绍。

静态渲染

采用"静态渲染"的区块在保存时会生成固定的前端输出并存储在数据库中。这些区块完全依赖其 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_block 和 render_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>

数据库中动态块的 HTML 表示(save)

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

当 save 为 null 时,块编辑器将跳过块标记验证过程,避免因频繁变化的标记而产生问题。

具有动态渲染功能的块也可以保存块的 HTML 表示作为备份。如果你提供了服务器端渲染回调,数据库中代表该块的 HTML 将被回调的输出替换,但如果你的块被停用(注册该块的插件被卸载)或你的渲染回调被移除,则会渲染此 HTML。

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

如果你在动态块中使用 InnerBlocks,则需要在 save 回调函数中使用 <InnerBlocks.Content/> 来保存 InnerBlocks。

其他资源