WordPress 块编辑器 core/post-date 块深度解析:属性、动态渲染与发布/修改日期变体全指南
【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg
本篇技术指南以 Gutenberg 开源仓库中core/post-date(Date)块为核心,系统讲解该动态块的block.json属性与 Supports 配置、服务器端渲染逻辑、编辑器端交互界面、Publish Date 与 Modified Date 两个变体,以及向后兼容的弃用迁移机制。读完本文,你将完整掌握如何在模板、查询循环(Query Loop)与主题开发中正确使用并深度定制该块,同时理解其底层源码实现(PHP 与 React 两侧)。
块概览:一个服务端渲染的动态块
core/post-date是 WordPress 块编辑器(Gutenberg)中用于展示自定义日期的主题类(Category:theme)核心块,定义于 packages/block-library/src/post-date/block.json。根据其自动生成的 API 文档(packages/block-library/src/post-date/README.md),它的关键元信息如下:
| 元信息项 | 值 |
|---|---|
| 块名(Name) | core/post-date |
| 分类(Category) | theme |
| API 版本(API Version) | 3 |
| 块类型(Block Type) | 动态块(Dynamic / server-rendered) |
| 文本域(textdomain) | default |
| 示例视口宽度(example.viewportWidth) | 350 |
block.json中同时给出了块标题Date与描述Display a custom date.。作为动态块,它不把 HTML 存进文章内容,而是在服务端按需渲染(详见下文"动态块与 Block Markup"一节),这也是它在查询循环、归档页中能随每篇文章动态变化的原因。
Attributes:datetime / format / isLink 三个核心属性
块的属性(Attributes)通过block.json的attributes属性声明,作用是定义可被编辑并持久化的数据字段。core/post-date共声明了三个属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
datetime | string | — | 要显示的日期时间值,Role 为content |
format | string | — | 日期显示格式(PHP 日期格式字符串,或特殊值human-diff) |
isLink | boolean | false | 是否为日期添加指向文章本身的链接,Role 为content |
对应源码(packages/block-library/src/post-date/block.json):
"attributes": { "datetime": { "type": "string", "role": "content" }, "format": { "type": "string" }, "isLink": { "type": "boolean", "default": false, "role": "content" } }三个属性的实际含义
datetime:标记为role: "content"的属性是块的"内容"核心,会直接出现在文章内容的块注释参数中。它既可以是显式写入的一个日期字符串,也可以通过 Block Bindings(块绑定)绑定到core/post-data数据源(见下文"变体"与"服务器端渲染"两节)。format:控制日期最终如何呈现。除 PHP 日期格式(如Y-m-d、F j, Y)外,还支持特殊值human-diff(人性化相对时间,如"2 hours ago")。为空时使用站点"常规设置"中的日期格式。isLink:false时日期只是纯文本<time>;true时日期会被包裹在指向该文章永久链接(permalink)的<a>标签内。
Supports:块支持的面板能力
supports声明块可被哪些"区块设置"能力接管。core/post-date的 Supports 配置(见 block.json 与 README 的 Supports 一节)整理如下:
| 支持项 | 值 | 说明 |
|---|---|---|
anchor | true | 允许设置 HTML 锚点(id) |
html | false | 不允许直接编辑 HTML(符合动态块定位) |
color.gradients | true | 支持渐变背景 |
color.link | true | 支持链接颜色 |
spacing.margin | true | 支持外边距 |
spacing.padding | true | 支持内边距 |
typography.fontSize | true | 支持字号 |
typography.lineHeight | true | 支持行高 |
typography.textAlign | true | 支持文本对齐 |
interactivity.clientNavigation | true | 支持客户端导航(站点编辑中的无刷新跳转) |
除 README 中列出的项外,block.json还声明了若干实验性能力:排版方面有__experimentalFontFamily(字体族)、__experimentalFontWeight(字重)、__experimentalFontStyle(字体风格)、__experimentalTextTransform(大小写变换)、__experimentalTextDecoration(文字装饰)、__experimentalLetterSpacing(字间距);边框方面有__experimentalBorder的radius/color/width/style四项。同时通过__experimentalDefaultControls指定默认开启的控件:颜色默认开背景、文本、链接;排版默认开字号;边框默认全开。
这些默认控件的意义在于:当主题或全局样式没有显式配置时,编辑器的"默认控件"会以合理的最小集自动呈现,避免侧栏过载。
Context:依赖的文章上下文数据
usesContext声明该块运行所需的外部上下文(README Context 一节):
postId:当前文章 ID —— 决定日期取哪篇文章、链接指向哪里;postType:当前文章类型 —— 编辑器用它加载文章类型标签(如"文章/页面")来动态生成Link to %s文案;queryId:所属查询循环(Query Loop)的 ID —— 用于判断块是否位于查询循环内部(编辑器中isDescendentOfQueryLoop = Number.isFinite( queryId ),见 edit.jsx)。
块本身不通过providesContext向外提供上下文。这意味着它必须处于能获取上述上下文的父级结构中(最典型的是查询循环、文章模板或单篇模板)才能正确渲染;脱离上下文时,编辑器中会以当前日期作为兜底预览值。
动态块与 Block Markup
因为它是动态块,文章内容里只保存一段块注释(Block Comment),真正的 HTML 由服务端渲染输出(README 的 Block Markup 一节):
<!-- wp:post-date /-->带属性时的完整形态类似:
<!-- wp:post-date {"format":"human-diff","isLink":true} /-->保存时save()返回null(见 deprecated.js 中save() { return null; }的历史形态,当前版本编辑设置见 index.js),即"不保存任何 HTML",这是所有动态块的共同特征,也是html: false的直接原因。
服务器端渲染原理:render_block_core_post_date 逐行拆解
服务端渲染回调定义在 packages/block-library/src/post-date/index.php,通过register_block_type_from_metadata( __DIR__ . '/post-date', array( 'render_callback' => 'render_block_core_post_date' ) )注册(第 98-105 行),并在init钩子上调用。函数签名接收$attributes、$content与$block(WP_Block实例),返回包裹在time标签中的文章日期。
1. 旧版(legacy)兼容分支
当既没有datetime属性、也没有针对datetime的 Block Bindings 配置时(第 22-43 行),函数判定这是没有datetime属性的旧版块,转而从块绑定源core/post-data取值:
$source = get_block_bindings_source( 'core/post-data' ); if ( isset( $attributes['displayType'] ) && 'modified' === $attributes['displayType'] ) { $source_args = array( 'field' => 'modified' ); } else { $source_args = array( 'field' => 'date' ); } $attributes['datetime'] = $source->get_value( $source_args, $block, 'datetime' );这里field可以是date(发布日期)或modified(修改日期),对应 PHP 侧get_the_date()/get_the_modified_date()。旧版displayType: 'modified'还会被加上wp-block-post-date__modified-date类(第 45-47 行)。
2. 空值处理
如果datetime为空(第 49-57 行),函数直接返回空字符串。注释指出:当块绑定到"最后修改日期"且该日期早于发布日期时会出现此情况——此时必须尊重并返回空值(该逻辑源自 WordPress/gutenberg#46839 的讨论)。
3. 日期格式化
- 若
format === 'human-diff'(第 62-69 行):使用human_time_diff()生成相对时间,并根据时间戳是否晚于当前时刻分别拼接__('%s from now')或__('%s ago')文案; - 否则(第 70-73 行):
format为空时回退到站点选项get_option( 'date_format' ),最终用wp_date( $format, $post_timestamp )输出,天然支持时区与多语言本地化。
4. 类名与包装结构
- 有
textAlign时追加has-text-align-{值}(第 75-77 行); - 设置了链接文字颜色时追加
has-link-color(第 78-80 行); - 用
get_block_wrapper_attributes()统一生成包裹属性(第 82 行),这是主题可控类的关键入口; - 核心输出(第 84-88 行):日期放在语义化
<time datetime="ISO 格式">标签中,datetime属性值经esc_attr、显示文本经esc_html转义;若isLink为真且存在postId上下文,再整体包一层指向get_the_permalink( $block->context['postId'] )的<a>,URL 经esc_url转义。
最终结构:
<div class="wp-block-post-date ..."> <a href="文章永久链接"> <time datetime="2026-09-16T06:00:00">September 16, 2026</time> </a> </div>5. 相关单元测试印证
仓库提供了专门的 PHP 单测 phpunit/blocks/render-block-core-post-date.php 来验证上述行为:
test_render_with_explicit_date_attribute:显式datetime属性会被原样包含在输出中(第 34-53 行);test_render_with_date_attribute_binding:Block Bindings 中的date/modified字段分别与get_the_date/get_the_modified_date结果一致,且绑定值会覆盖显式回退值(第 55-105 行);test_render_legacy_block:无datetime的旧版块按displayType回退到date/modified(第 110-131 行);test_render_modified_date_before_publish_date:修改日期早于发布日期时输出空字符串(第 133-159 行)。
这些测试直接印证了前文所述的 legacy 分支、绑定覆盖与空值策略。
编辑器端体验:工具栏与侧栏的完整交互
编辑器侧的实现位于 packages/block-library/src/post-date/edit.jsx,核心组件PostDateEdit提供了:
- 首次挂载默认值:
datetime未定义时用__unstableMarkNextChangeAsNotPersistent()标记一次不持久化的变更并写入当前日期(第 60-65 行),目的是把新版块与默认取文章发布日期的旧版块区分开; - 工具栏"修改日期":非查询循环(或默认编辑模式)下显示
BlockControls工具栏,铅笔图标按钮(@wordpress/icons的pencil,标题Change Date)弹出__experimentalPublishDateTimePicker日期时间选择器,支持 12/24 小时制判定(依据站点时间格式)与dmy/mdy/ymd日期顺序本地化(第 119-173 行); - 侧栏设置(ToolsPanel):
InspectorControls内是ToolsPanel(第 175-234 行),含两个默认显示的面板项:- Date Format(日期格式):
__experimentalDateFormatPicker,默认格式取站点设置date_format(第 187-202 行); - Link to %s(链接到文章):
ToggleControl开关,标签会利用postType.labels.singular_name动态生成,例如文章类型为"文章"时显示"链接到文章"(第 203-232 行);
- Date Format(日期格式):
- 12 小时制判定函数:
is12HourFormat()(第 241-247 行)通过正则/(?:^|[^\\])[aAgh]/检测格式串中是否存在未转义的 12 小时制字符(a、A、g、h)。对应的 test/edit.jsdom.test.js 用参数化用例覆盖了H:i(false)、g:i A(true)、\g\r\e\a\t(转义字符,false)等边界情况。
编辑器预览同样遵循"human-diff用humanTimeDiff()、其余用dateI18n()"的双分支逻辑(第 96-105 行),与 PHP 侧渲染保持一致。
变体:Post Date 与 Modified Date
packages/block-library/src/post-date/variations.js 定义了该块的两个区块变体,均基于 Block Bindings 的core/post-data源:
| 变体名 | 标题 | 描述 | 绑定字段 | 附加类 |
|---|---|---|---|---|
post-date | Post Date | 展示文章的发布日期 | field: 'date' | — |
post-date-modified | Modified Date | 展示文章的最后更新日期 | field: 'modified' | wp-block-post-date__modified-date |
变体的attributes通过metadata.bindings.datetime挂接数据源,isActive判定依据是绑定源与args.field的取值(第 19-24、41-45 行)。scope为['inserter', 'transform'],即既可从插入器(Inserter)单独插入,也可在块间转换。编辑器侧还会根据当前激活变体决定工具栏标题是Publish Date还是Date(edit.jsx),并且在 Modified Date 变体激活时隐藏"修改日期"按钮(第 119-121 行)。
两个变体在区块插入器界面表现为两个独立条目:"文章日期(Post Date)"与"修改日期(Modified Date)",方便作者直接插入"最后更新"日期而无需手动绑定。
向后兼容与弃用迁移机制
core/post-date在历次迭代中积累了大量历史形态,packages/block-library/src/post-date/deprecated.js 按[v4, v3, v2, v1]顺序登记了 4 个旧版本,新版本排最前以获得更高匹配优先级:
- v4:已含
datetime属性,仅迁移历史textAlign(migrate: migrateTextAlign); - v3:迁移块绑定参数名
key→field(第 147-174 行),这是core/post-data源参数统一为field的兼容步骤; - v2:面向既无
datetime也无绑定的旧块,将displayType(date/modified)转换为metadata.bindings.datetime结构,modified同时追加wp-block-post-date__modified-date类(第 249-272 行); - v1:最早的仅
textAlign/format/isLink版本,迁移字体族与文本对齐(第 314-316 行)。
这套机制保证了历史文章中的旧注释在块解析时能被逐级识别并升级到当前结构,对动态块尤为重要——旧内容里的<!-- wp:post-date {"displayType":"modified"} /-->也能在新版本中正确渲染为修改日期。
样式与主题集成要点
样式文件 packages/block-library/src/post-date/style.scss 非常克制,仅一行核心规则:
.wp-block-post-date { // This block has customizable padding, border-box makes that more predictable. box-sizing: border-box; }由于块支持自定义内边距,显式声明box-sizing: border-box使 padding 计算更可预期。其余视觉样式(字号、颜色、行高、对齐、边框、链接色等)全部交由块级 Supports 对应的生成类与全局样式接管,主题开发者可以通过以下途径定制:
- 使用
.wp-block-post-date选择器覆写整体样式; - 利用
has-text-align-*、has-link-color等工具类做定向调整; - 在主题的
theme.json中配置core/post-date的排版、颜色、间距等默认样式。
实践场景与使用建议
- 查询循环内:在 Query Loop 模板块中插入"日期"块,它会自动使用
postId上下文渲染每篇文章的发布日期;isLink打开后整篇可点击,常用于博客卡片列表; - 单篇模板:在单篇文章模板中配合标题块展示发布时间;"修改日期"变体适合教程、文档类站点,告诉读者内容最后更新时间;
- 人性化时间:设置
format: 'human-diff'可获得"3 days ago"式相对时间,适合资讯流场景;注意 PHP 侧会用human_time_diff兜底,未来时刻显示"from now"; - 主题定制:通过
.wp-block-post-date类与块级 Supports 的组合即可完成绝大多数视觉定制,无需编写自定义渲染回调。
总结
core/post-date是理解"动态块 + Block Bindings + 变体 + 弃用迁移"完整范式的绝佳样本:block.json声明属性与能力,index.php的render_block_core_post_date()完成服务端渲染与旧版兼容,edit.jsx提供所见即所得的编辑器体验,variations.js以绑定方式派生发布/修改日期两个变体,deprecated.js保证历史内容平滑升级,而 phpunit/blocks/render-block-core-post-date.php 与 test/edit.jsdom.test.js 从 PHP 与前端两侧锁定了行为。掌握这条链路后,你不仅能熟练使用该块,也能为其在主题与站点编辑中的扩展打下坚实基础。
【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考