Gutenberg 区块编辑器文档

title: "区块的静态或动态渲染" post_status: publish comment_status: open taxonomy: category: - gutenberg-docs post_tag: - Fundamentals - Getting Started - Repos


区块的静态或动态渲染

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

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

静态渲染

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

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

查看站点标题区块中的动态渲染示例
[站点标题](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/site-title) 区块使用以下 [`render_callback`](https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/site-title/index.php):
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`](https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/site-title/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,这会告知编辑器仅将块分隔符注释(以及任何现有的块属性)保存到数据库。然后这些属性会被传递给服务器端渲染回调,由它决定如何在前端显示该块。

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

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

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

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

其他资源