搜索全站
主题 13 分钟阅读

区块主题(FSE)与传统主题的区别:theme.json、模板编辑器与 PHP 模板

区块主题不是“换了个编辑器”。本文从模板层级、配置方式、渲染链路三个层面讲清 FSE 主题与传统 PHP 主题的本质差异,附 theme.json 与 templates 结构示例。

U
UFO_PF 2022-06-12 · 阅读 13 分钟
区块 主题
阅读提示
本文约 5,129 字,预计阅读 13 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:后台多了一个“外观 → 编辑器”,然后呢

WordPress 5.9 引入区块主题(Block Themes / FSE,Full Site Editing)之后,很多站长的第一个困惑是:明明还在用旧主题,后台为什么没有“站点编辑器”?装了 Twenty Twenty-Five 后又发现模板文件变成了 .html,里面全是 <!-- wp:xxx --> 这种注释。

这两种形态的差异,远不止“编辑器界面变了”。它涉及模板从哪来、样式由谁定义、用户能在多大程度上改首页结构这三个根本问题。理解这三点,你才能判断自己的项目该用哪种主题,以及从传统主题迁移到区块主题的路线该从哪里起步。

原理分析:渲染链路的三个不同点

第一,模板来源不同。

传统主题走 PHP 模板层级:WordPress 根据请求类型在主题目录里找 single.php → singular.php → index.php,找不到就一层层往上兜底。文件里写的是 PHP 代码。

区块主题走的是同一套模板层级,但模板是存在数据库里(wp_template 文章类型)或主题 templates/ 目录里的 HTML 文件,内容是区块标记(block markup)。首次 install 时,核心会把主题目录里的 .html 模板“固化”为可编辑的版本,之后用户在站点编辑器里的修改就存在数据库里,覆盖了磁盘上的文件版本。

第二,样式与设置的来源不同。

传统主题的绝大部分样式写死在 style.css 和 functions.php 注册的 CSS 里,用户可以通过 small custom CSS 修改;区块主题则把调色板、字号、间距规则、布局宽度写在 theme.json 里,由核心统一生成 CSS 变量(形如 --wp--preset--color--accent-1),并为每个区块生成内联样式。

这带来的直接结果是:用户在站点编辑器里改了调色板,所有使用该 preset 的区块同步变色;传统主题改颜色得改 CSS。

第三,用户可修改的范围不同。

传统主题下用户能改的只有:菜单、小工具、部分 Customizer 选项。区块主题下用户可以直接编辑页头文件、文章模板、404 页面。自由度极高,代价是“这个站点能不能被客户改坏”——这是交付前必须明确的边界。

对比项 传统主题 区块主题
模板文件 .php templates/*.html + wp_template CPT
页头页脚 header.php/footer.php parts/*.html(template part)
样式配置 style.css + 零散 CSS theme.json + 预设 CSS 变量
用户改结构 基本不能 可在站点编辑器改模板
开发门槛 需懂 PHP 懂 HTML/区块标记即可上手

保姆级实操

第一步:先看懂 templates 目录里的 HTML 到底在说什么。

一个最小的 templates/index.html:

<!-- wp:template-part {"slug":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
    <!-- wp:query {"queryId":0,"query":{"perPage":10,"postType":"post"}} -->
        <!-- wp:post-template -->
            <!-- wp:post-title {"isLink":true} /-->
            <!-- wp:post-excerpt /-->
        <!-- /wp:post-template -->
    <!-- /wp:query -->
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

这些 <!-- wp:xxx --> 是区块的分隔注释,由 WP_Block_Parser 解析为区块树,再逐个渲染。{"isLink":true} 是区块属性(attributes)。

第二步:看懂 theme.json 与 CSS 变量的映射关系。

theme.json 里定义的 preset 会被核心转成 CSS 自定义属性:

/* theme.json 中 slug 为 accent-1 的颜色 */
:root {
  --wp--preset--color--accent-1: #0b6e4f;
}

/* 在主题自己的样式里引用 */
.wp-block-button__link {
  background-color: var(--wp--preset--color--accent-1);
  padding-inline: var(--wp--preset--spacing--30);
}

所以在区块主题里,你写的 CSS 应尽量引用这些变量,而不是写死色值。

第三步:给传统主题加上局部的区块能力(混合路线)。

不必一步到位换成区块主题。传统主题可以渐进支持:

<?php
// functions.php —— 传统主题也能支持部分 FSE 特性
add_action( 'after_setup_theme', function () {
    // 让区块使用主题的配色与排版
    add_theme_support( 'wp-block-styles' );
    add_theme_support( 'align-wide' );
    add_theme_support( 'editor-styles' );
    add_theme_support( 'responsive-embeds' );

    // 注册专属的 template part 区域(页头/页脚),供站点编辑器使用
} );

add_filter( 'default_template_part_areas', function ( $areas ) {
    $areas[] = array(
        'area'        => 'sidebar-promo',
        'label'       => '推广侧边栏',
        'description' => '出现在归档页右侧的推广位',
        'icon'        => 'megaphone',
        'area_tag'    => 'aside',
    );
    return $areas;
} );

第四步:给自定义文章类型提供初始区块模板。

add_filter( 'post_type_template_hierarchy', function () {
    return array( 'custom-post-template' );
} );

register_post_type( 'product', array(
    'public'       => true,
    'show_in_rest' => true,
    'template'     => array(
        array( 'core/paragraph', array( 'placeholder' => '写一句产品简介' ) ),
        array( 'core/image' ),
        array( 'core/heading', array( 'level' => 3, 'content' => '规格参数' ) ),
    ),
    'template_lock' => 'insert', // 允许移动现有区块,不允许新增新类型
) );

template_lock 的取值 all、insert、content 是区块 API 的标准参数。

第五步:检查主题当前跑在哪条路上。

# 有 theme.json 且 templates 目录存在 HTML,即为区块主题
ls wp-content/themes/当前主题/theme.json
ls wp-content/themes/当前主题/templates/

# 数据库中被用户改写过的模板(站点编辑器保存的内容)
wp post list --post_type=wp_template --fields=ID,post_name,post_status

第六步:用命令行生成本地区块骨架。

wp scaffold block local-banner --title="本地横幅" --namespace=mangfei

这会生成 block.json + src/ 源码结构,是现代区块开发(@wordpress/scripts 编译)的标准起点。

常见踩坑

  1. 手工删了 templates/ 里的某个 html 但站点编辑器里还留着。 remember:用户修改后的模板在库里。要重置,请先删除对应的 wp_template 记录。
  2. 把 theme.json 当成万能 CSS 文件。它只负责 preset 与全局设置,复杂布局仍须写区块级 CSS。
  3. 忽略 --wp--preset--* 变量而写死色值。用户改了调色板后你的样式不会跟随。
  4. 以为区块主题不需要 PHP。涉及 REST 字段、自定义模板层级、区块样式注册仍需 PHP(通常在 functions.php 配合 theme.json 的 styles)。
  5. 给客户交付后没锁权限。站点编辑器让客户能随意改模板,交付前务必考虑角色权限(如限制 edit_theme_options)。
  6. 在 child theme 里整份拷贝父主题 theme.json。差异部分覆写即可,否则父主题新特性接收不到(同 258 篇原则)。
  7. 案例:某站点换了 Twenty Twenty-Three 后,客户自己在站点编辑器里改了 archive 模板,删掉了 wp:post-term 等诸多区块,导致归档页没有分页。更新子树那时因为库里的版本覆盖了磁盘版本,怎么升级主题都不变。最后用 wp post list --post_type=wp_template 找到那条记录的 ID,改成 draft 恢复默认模板才解决。区块主题的“用户数据即模板”是它最大的特点,也是最需要运维规范的地方。

总结

三句话总结差异:模板从 PHP 变成了 HTML + 区块标记;样式从散落的 CSS 变成了 theme.json 驱动的 CSS 变量;用户的编辑权从“只见选项”扩展到“可见结构”。

如果你的项目在追求:(1)内容运营者可以自助调整版式;(2)与 Gutenberg 生态长期一致;(3)不需大量 PHP 定制 —— 那优先选区块主题(分阶段的迁移推进见从传统主题迁移到区块主题的路线)。如果你需要复杂的动态逻辑、遗留大量 shortcode/旧 meta 或者有强定制型模板需求,传统主题或混合路线更务实。混合(渐进)方案往往是现阶段最稳的一条。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。