本文约 7,594 字,预计阅读 19 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:编辑在重复搭同样的积木
客户站点有三十个落地页,每页都是「大标题 + 副标题 + 两个按钮 + 三栏特性卡 + FAQ」。编辑每次都要从空白页开始:插入封面区块、调对齐、插入列区块、切成三列、每列里再插标题段落……半小时过去了,做出来的间距还和上一页差两个像素。
区块模式(Block Patterns)就是把这套「积木组合」预先拼好存起来,编辑在插入器里点一下,整段结构连同内容一起进来,之后再改文字即可。它和「可复用区块」的区别是:模式是模板,插入后与原模式脱离关系,改一篇不影响其他;可复用区块是实例,改一处全站同步。需要全站统一更新的选可复用区块,需要「结构一致、内容各异」的选模式。
原理分析:三种来源与加载顺序
WordPress 的区块模式有三个来源:
| 来源 | 位置 | 说明 |
|---|---|---|
| 核心捆绑 | core 分类 |
WP 自带的几十个模式,英文为主 |
| 远程模式 | pattern directory(patterns.api.w.org) | 从 WordPress.org 拉取,国内服务器常因网络慢拖累编辑器 |
| 主题/插件注册 | patterns/*.php 或 register_block_pattern() |
自己写的,可控性最高 |
主题目录下放 patterns/ 文件夹时,WordPress 会自动扫描里面的 PHP 文件,读取文件头的注释字段来注册,不需要写一行 PHP 代码——这是区块主题(FSE)的标准做法,内部由 register_theme_block_patterns() 完成。经典主题也可以用,只要主题声明了区块支持。
文件头支持的字段有:Title(必填)、Slug(必填,格式 theme-slug/pattern-name)、Categories、Description、Keywords、Viewport Width、Block Types(把模式绑定到某个区块的「初始内容」)、Post Types、Inserter(yes/no,是否在插入器里显示)。
国内站点强烈建议关闭远程模式:编辑器每次打开都要请求 patterns.api.w.org,超时会让插入器转圈好几秒。
保姆级实操
第一步:用目录方式注册,零 PHP 代码
在主题根目录建 patterns/hero-cover.php:
<?php
/**
* Title: 首页主视觉
* Slug: mimangfei/hero-cover
* Categories: featured, header
* Description: 带大标题、副标题与双按钮的全宽主视觉区
* Keywords: hero, banner, 首屏
* Viewport Width: 1200
*/
?>
<!-- wp:cover {"url":"<?php echo esc_url( get_template_directory_uri() ); ?>/assets/img/hero.jpg","dimRatio":50,"overlayColor":"contrast","align":"full","style":{"spacing":{"padding":{"top":"var(--wp--preset--spacing--60)","bottom":"var(--wp--preset--spacing--60)"}}}} -->
<div class="wp-block-cover alignfull"><span aria-hidden="true" class="wp-block-cover__background has-contrast-background-color has-background-dim"></span><div class="wp-block-cover__inner-container">
<!-- wp:heading {"textAlign":"center","level":1,"style":{"typography":{"fontSize":"3rem"}}} -->
<h1 class="wp-block-heading has-text-align-center" style="font-size:3rem">为外贸独立站打造的 WordPress 主题</h1>
<!-- /wp:heading -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">轻量、合规、可维护,交付后客户自己就能改。</p>
<!-- /wp:paragraph -->
<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
<div class="wp-block-buttons">
<!-- wp:button {"backgroundColor":"accent"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-accent-background-color has-background wp-block-button__link--href">查看演示</a></div>
<!-- /wp:button -->
<!-- wp:button {"className":"is-style-ghost"} -->
<div class="wp-block-button is-style-ghost"><a class="wp-block-button__link wp-block-button__link--href">联系我们</a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div></div>
<!-- /wp:cover -->
重点是注释头那段,正文里的区块标记(block markup)可以从编辑器里「复制为代码块」拿到:在编辑器中选中区块,点右上角菜单选「复制」,粘贴到文本编辑器里就是这段注释标记。手写很容易因为属性转义出错,复制是最可靠的做法。
第二步:用 PHP 动态注册(内容需要计算时)
add_action( 'init', 'mimangfei_register_patterns' );
function mimangfei_register_patterns() {
register_block_pattern_category(
'mimangfei-pages',
array(
'label' => __( '页面模板', 'mimangfei' ),
)
);
register_block_pattern(
'mimangfei/cta-box',
array(
'title' => __( '行动号召卡片', 'mimangfei' ),
'description' => __( '带标题、说明与按钮的居中标语区', 'mimangfei' ),
'categories' => array( 'mimangfei-pages', 'call-to-action' ),
'keywords' => array( 'cta', '按钮', '转化' ),
'viewportWidth' => 900,
'content' => '<!-- wp:group {"style":{"spacing":{"padding":{"top":"var(--wp--preset--spacing--50)","bottom":"var(--wp--preset--spacing--50)"}}},"backgroundColor":"base-2","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-base-2-background-color has-background">
<!-- wp:heading {"textAlign":"center"} --><h2 class="wp-block-heading has-text-align-center">准备好开始了吗</h2><!-- /wp:heading -->
<!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center">留下需求,我们会在一个工作日内回复方案。</p><!-- /wp:paragraph -->
<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} --><div class="wp-block-buttons"><!-- wp:button --><div class="wp-block-button"><a class="wp-block-button__link wp-block-button__link--href">联系顾问</a></div><!-- /wp:button --></div><!-- /wp:buttons -->
</div>
<!-- /wp:group -->',
)
);
}
注意 register_block_pattern_category 要先于 register_block_pattern 调用,否则分类会出现但未归类。也可以在 content 里拼接变量(比如主题目录 URI),这是目录方式做不到的。
第三步:关闭远程模式与核心模式
add_filter( 'should_load_remote_block_patterns', '__return_false' );
add_action( 'after_setup_theme', 'mimangfei_disable_core_patterns' );
function mimangfei_disable_core_patterns() {
remove_theme_support( 'core-block-patterns' );
}
should_load_remote_block_patterns 只关远程拉取,remove_theme_support( 'core-block-patterns' ) 会连核心捆绑的模式一起关掉。建议只关远程,保留核心——但核心模式多为英文内容,中文站也可以全关,只留自己注册的。
第四步:把模式绑定到区块(Block Types)
在 patterns/ 文件头加一行,可以让新建某个区块时自动套用这个模式:
<?php
/**
* Title: 定价表起始内容
* Slug: mimangfei/pricing-starter
* Categories: mimangfei-pages
* Block Types: core/table
* Inserter: no
*/
?>
Inserter: no 表示不在插入器里显示,只作为区块的初始内容——非常适合「表格、图库」这类用户不知从何下手的区块。
第五步:按文章类型限制模式
register_block_pattern(
'mimangfei/product-intro',
array(
'title' => __( '产品介绍结构', 'mimangfei' ),
'categories' => array( 'mimangfei-pages' ),
'postTypes' => array( 'product', 'page' ),
'content' => '<!-- wp:paragraph --><p>产品亮点说明</p><!-- /wp:paragraph -->',
)
);
postTypes 限定它只在指定文章类型出现,避免编辑在写普通文章时被一堆无关模式干扰。
第六步:卸载不需要的模式
add_action( 'init', 'mimangfei_unregister_patterns', 20 );
function mimangfei_unregister_patterns() {
unregister_block_pattern( 'core/two-buttons' );
unregister_block_pattern_category( 'query' );
}
优先级给到 20,确保晚于核心的注册时机。
常见踩坑
- Slug 少了主题前缀:
hero这种短名会与核心或其他插件冲突,必须写成mimangfei/hero。 - 注释头缩进或格式错误:
Slug:前有空格、字段拼写错(如Category少 s),都会导致文件被跳过且不报错。 - block markup 属性里的引号未转义:PHP 文件里用双引号包裹 JSON 属性时,内部引号要用
"或改写为单引号拼接,否则模式插入后区块报错「此块包含意外或无效的内容」。 - 关掉远程后又抱怨没素材:关闭前先把官方模式里能用的手动复制进自己的 patterns 目录。
- 模式里的图片路径写死:主题换域名或换目录名后图片全裂,用
get_template_directory_uri()动态拼接,或改用媒体库 URL。 - 案例:某站
patterns/目录下放了 40 个模式文件,其中一个忘了写Slug,WordPress 扫描时静默跳过;更糟的是另一个文件写了// 注释单行注释,导致整个文件的 mark-up 被当成纯文本输出,插入后页面上出现一整段<!-- wp:heading -->源码。后来加了 CI 步骤,用正则校验每个文件头都必须同时包含 Title 与 Slug 才允许提交。 Viewport Width不写:插入器缩略图会被拉伸变形,编辑难以分辨,建议统一填 1200 或实际宽度。- 模式引用了主题自定义区块样式但未注册:插入后看到的是无样式裸结构,确认
区块样式变体里注册的变体类名与模式中的className一致。
总结
落地顺序:先把站点重复度最高的三个布局抽成模式(首屏、特性三栏、FAQ),放进 patterns/ 目录;需要动态内容或条件判断的部分改用 register_block_pattern();上线前关闭远程模式并把 Inserter: no 用在该用的地方。模式的价值不在于多,而在于「编辑最常用的那几次点击」被省掉,所以宁可精挑 5 个也别堆 50 个。想要进一步减少重复劳动,可配合 区块样式变体 统一外观,或按 主题打包与发布规范 把模式一起交付给客户。
