Gutenberg core/read-more 块深度解析:服务端渲染的""链接块
【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg
core/read-more 是 Gutenberg(WordPress 块编辑器项目)内置的主题类动态块,用于在文章列表、查询循环等场景中展示指向文章、页面或其他内容类型的""链接。本文以 read-more 块官方文档 为主体骨架,结合该块在仓库中的 block.json、服务端渲染实现 与 编辑端组件 源码,完整解析其属性定义、支持能力、渲染原理与编辑器交互,读完即可在自己的主题或块开发中精准使用并二次扩展该块。
一、块概览:一个纯服务端渲染的动态块
按官方文档的块 API 定义,core/read-more具有以下注册元信息:
| 项目 | 值 |
|---|---|
| 块名称(Name) | core/read-more |
| 分类(Category) | theme(主题类) |
| API 版本(API Version) | 3 |
| 块类型(Block Type) | Dynamic(动态块,服务端渲染) |
该块属于动态块(Dynamic Block):它由服务器在渲染时生成最终 HTML,而不会把静态 HTML 保存进文章内容。这也决定了它通常在**查询循环(Query Loop)**等模板块内部被反复渲染——每次渲染时根据当前上下文中提供的postId动态生成指向对应文章的链接,实现"一篇文章一个链接"的效果。
二、块注册与元数据:block.json 如何定义该块
与 Gutenberg 中所有通过register_block_type_from_metadata注册的块一致,core/read-more的块元数据集中在 block.json:
{ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, "name": "core/read-more", "title": "Read More", "category": "theme", "description": "Displays the link of a post, page, or any other content-type.", "textdomain": "default", "attributes": { "content": { "type": "string", "role": "content" }, "linkTarget": { "type": "string", "default": "_self" } }, "usesContext": [ "postId" ], "supports": { "anchor": true, "html": false, "color": { "gradients": true, "text": true }, "typography": { "fontSize": true, "lineHeight": true, "__experimentalFontFamily": true, "__experimentalFontWeight": true, "__experimentalFontStyle": true, "__experimentalTextTransform": true, "__experimentalLetterSpacing": true, "__experimentalTextDecoration": true, "__experimentalDefaultControls": { "fontSize": true, "textDecoration": true } }, "spacing": { "margin": [ "top", "bottom" ], "padding": true, "__experimentalDefaultControls": { "padding": true } }, "__experimentalBorder": { "color": true, "radius": true, "width": true, "__experimentalDefaultControls": { "width": true } }, "interactivity": { "clientNavigation": true } }, "style": "wp-block-read-more" }几个关键点:
- 注册入口:PHP 侧通过
register_block_type_from_metadata( __DIR__ . '/read-more', ... )以目录方式加载元数据,见 index.php,并挂载在init钩子上;JS 侧则通过 init.js 调用 index.js 中的init()完成编辑端注册。 - 样式句柄:
"style": "wp-block-read-more"对应 style.scss,该样式由构建流程编译后随块按需加载。 html: false:禁止用户直接在代码编辑器中书写原始 HTML,保证该块的输出完全由服务端渲染逻辑控制。
三、属性(Attributes)详解
官方文档给出的属性定义(定义于 block.json 的attributes属性中):
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
content | string | — | 角色(Role)为content,即块的内容文本 |
linkTarget | string | "_self" | 链接的打开方式(target属性值) |
3.1 content:链接文字
content是块的内容角色属性,存的是""链接上显示的文字。它有两个特殊之处:
- 默认回退:当
content为空时,服务端渲染会回退到默认文案Read more(本地化字符串,见下文渲染实现); - 富文本编辑:在编辑器中它不是普通文本框,而是
RichText组件渲染的可直接编辑链接文字(见 edit.jsx),且设置了withoutInteractiveFormatting禁用链接内部的内联格式。
3.2 linkTarget:链接打开方式
linkTarget的默认值是"_self"(当前窗口打开)。编辑器侧通过设置面板(Inspector Controls)中的Open in new tab开关控制:开启时设为"_blank",关闭时重置为"_self",见 edit.jsx。
在 PHP 渲染时该值会被写入<a>标签的target属性:
esc_attr( $attributes['linkTarget'] )完整代码见 index.php。
四、支持能力(Supports):样式与布局的可定制范围
Supports 定义于 block.json 的supports属性中,官方文档列出的能力如下:
- anchor:
true——允许为该块设置 HTML 锚点(id属性),便于页内锚点跳转。 - html:
false——不支持原始 HTML 编辑。 - color:
gradients: true、text: true——支持渐变背景与文字颜色(注意:这里未开放背景纯色,仅开放了渐变与文字色)。 - typography:
fontSize、lineHeight为true;同时开启了实验性排版能力__experimentalFontFamily(字体)、__experimentalFontWeight(字重)、__experimentalFontStyle(样式)、__experimentalTextTransform(大小写转换)、__experimentalLetterSpacing(字距)、__experimentalTextDecoration(文本装饰),默认控制项为fontSize与textDecoration。 - spacing:
margin仅开放top与bottom两个方向;padding为true全方向开放,默认控制项为padding。 - interactivity:
clientNavigation: true——支持客户端导航(在站点编辑/前台交互式导航中平滑切换页面,避免整页刷新)。
需要说明的是,block.json 中还额外配置了__experimentalBorder(颜色、圆角、宽度,默认控制项为width),这一项属于块元数据中的实验性支持,编辑器据此在样式面板中渲染对应的边框控制项。这些能力共同决定了用户在编辑器"样式"侧栏里能看到哪些定制选项。
五、上下文(Context):块如何拿到 postId
core/read-more通过usesContext: [ "postId" ](见 block.json)消费由外层块提供的postId上下文。
官方文档的 Context 一节明确指出其唯一依赖的上下文是postId。这也解释了为什么该块脱离查询循环等提供postId的容器时无法渲染——服务端渲染函数在拿不到postId时会直接返回空字符串:
if ( ! isset( $block->context['postId'] ) ) { return ''; }见 index.php。因此它的典型宿主是查询循环(Query Loop)块或文章列表模板:外层块遍历文章并下发postId,read-more块随即为每一篇文章生成对应链接。
六、服务端渲染实现:render_block_core_read_more 全流程
动态块的核心逻辑在 index.php 的render_block_core_read_more( $attributes, $content, $block )函数中,自 WordPress 6.0.0 起提供。完整流程如下:
- 上下文校验:若
$block->context['postId']不存在则返回空字符串(不输出任何 HTML)。 - 获取文章标题:
get_the_title( $post_ID )取文章标题;若标题为空,则回退为本地化文案untitled post %s(%s为文章 ID),用作无障碍描述。 - 构造屏幕阅读器文本:以
: %s(%s为文章标题或 ID)拼出screen-reader-text内容,保证读屏软件能说清楚"这个链接指向哪篇文章"。 - 计算对齐类名:若存在
justifyContent属性,则附加is-justified-{value}类(对应查询循环中对齐设置)。 - 获取包装属性:
get_block_wrapper_attributes()生成class、id(锚点)、内联样式等包装属性,最终输出到<a>标签上。 - 确定链接文字:
$more_text优先使用content属性(经wp_kses_post过滤),为空时回退到本地化文案Read more。 - 输出链接:
return sprintf( '<a %1$s href="%2$s" target="%3$s">%4$s<span class="screen-reader-text">%5$s</span></a>', $wrapper_attributes, esc_url( get_the_permalink( $post_ID ) ), esc_attr( $attributes['linkTarget'] ), $more_text, $screen_reader_text );可见最终生成的 HTML 结构是:带包装属性(类名、锚点、样式)的<a>标签,href指向get_the_permalink( $post_ID )返回的文章永久链接,target由linkTarget决定,内部依次是可见链接文字和仅供读屏软件识别的screen-reader-text补充说明。所有输出均经过esc_url/esc_attr/wp_kses_post转义,保证了 XSS 安全性。
注册部分通过init钩子完成:
function register_block_core_read_more() { register_block_type_from_metadata( __DIR__ . '/read-more', array( 'render_callback' => 'render_block_core_read_more', ) ); } add_action( 'init', 'register_block_core_read_more' );七、编辑器交互:富文本直改 + 设置面板
编辑端组件位于 edit.jsx,由ReadMore函数组件实现,包含两大块:
1. 设置面板(InspectorControls):使用__experimentalToolsPanel/ToolsPanelItem组件构建"设置"面板,其中唯一的控制项是Open in new tab开关(ToggleControl)。开关状态由linkTarget === '_blank'决定,切换时在'_blank'与'_self'之间写入linkTarget;面板的"重置全部"动作会把linkTarget重置回_self。
2. 富文本编辑区:使用RichText组件直接渲染块主体,tagName="a"使其在编辑器中即以链接形态呈现,placeholder为Read more,value绑定content属性,onChange同步写回。同时配置了__unstableOnSplitAtEnd:当光标在末尾回车拆分块时,会在其后插入默认块(createBlock( getDefaultBlockName() )),延续 Gutenberg 块编辑器的拆分交互习惯。
块图标取自@wordpress/icons的link图标,并在 index.js 中提供了一个example示例(content: 'Read more'),供块目录与预览场景使用。
八、样式与可访问性设计
style.scss 定义了wp-block-read-more的前台样式:
.wp-block-read-more { display: block; width: fit-content; &:where(:not([style*="text-decoration"])) { text-decoration: none; &:focus, &:active { text-decoration: none; } } }设计要点:
display: block配合width: fit-content,使链接块按内容收缩宽度、独立成行,便于在文章列表中垂直排布;- 通过
:where(:not([style*="text-decoration"]))只在用户未通过排版设置显式指定文本装饰时去掉下划线,避免覆盖用户的样式面板配置; - 服务端渲染中嵌入的
screen-reader-text为链接补充了"指向哪篇文章"的无障碍信息,是对可访问性的显式支持(屏幕阅读器用户能听到例如 "Read more: 我的文章标题")。
九、动态块的内容存储格式
因为这是动态块,文章内容中不会保存最终 HTML,只保存块注释标记:
<!-- wp:read-more /-->从官方文档的 Block Markup 一节可知,该块在文章内容中以自闭合块注释形式存储(无属性的默认形态)。如果设置了属性,则会以 JSON 形式内联在注释中,例如:
<!-- wp:read-more {"content":"继续阅读","linkTarget":"_blank"} /-->实际渲染时由 PHP 服务端根据注释中的属性与上下文中的postId实时生成链接。这意味着即便文章标题后续发生变化,链接指向也不会失效;但同时也意味着前台必须经过 WordPress 渲染管线才能得到最终 HTML。
十、典型应用场景与扩展方向
综合源码实现,core/read-more块最典型的落地场景是:
- 查询循环(Query Loop)模板:在文章卡片布局中放置该块,自动为循环内每篇文章生成""链接——这正是它通过
usesContext: postId消费上下文的设计初衷; - 首页/归档页的自定义文章列表:与
latest-posts、post-excerpt等块组合使用(这些块在 block-library 源码 中同样引用read-more相关渲染逻辑),构成"摘要 + "的经典卡片结构; - 多语言与品牌化定制:通过
content属性替换默认的Read more文案,例如改为"继续阅读"、"查看详情"等,配合linkTarget决定是否新窗口打开。
若需在自有主题中复刻该块的注册方式,可直接参考 index.php 的register_block_type_from_metadata+render_callback模式,将block.json中supports、attributes、usesContext的配置迁移到自定义块中,即可获得与本块一致的编辑器体验与渲染行为。
参考资料
- read-more 块 API 文档
- block.json 元数据定义
- 服务端渲染实现 index.php
- 编辑端组件 edit.jsx
- 块入口与注册 index.js、init.js
- 前台样式 style.scss
【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考