Gutenberg Latest Posts 核心块完整指南:从 block.json 属性到服务端渲染实现

发布时间:2026/9/17 1:30:42
Gutenberg Latest Posts 核心块完整指南:从 block.json 属性到服务端渲染实现 Gutenberg Latest Posts 核心块完整指南从 block.json 属性到服务端渲染实现【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenbergcore/latest-posts最新文章是 Gutenberg 编辑器中一个典型的动态Dynamic核心块它在服务器端通过WP_Query实时查询已发布文章并渲染 HTML不在文章内容中保存静态输出。本文以 packages/block-library/src/latest-posts/README.md 为骨架结合 block.json、服务端渲染实现 index.php、编辑器实现 edit.jsx 与废弃迁移逻辑 deprecated.js 等源码系统讲解该块的全部属性、Supports 能力、渲染流程与迁移机制帮助你理解如何配置、扩展并排查相关问题。一、块基本信息README 中定义了该块的元信息这些信息全部由 block.json 声明项目值说明名称Namecore/latest-posts在文章内容与 REST API 中使用的唯一标识分类Categorywidgets小组件位于块选择器的小组件分类API 版本3采用 Block API 第 3 版支持supports中的 blockGap 等新能力块类型Dynamic动态由服务器渲染输出由 PHP 端render_callback实时生成关键词Keywordsrecent posts帮助用户在块选择器中搜索定位文本域textdomaindefault使用核心自带的翻译文本域从前端注册入口 index.js 可以看到块的图标使用postList并且通过initBlock工具完成注册。由于该块是动态块其save返回null见settings中未定义 save 以及 deprecated.js 中所有旧版本的save: () null。动态块的含义README 明确指出这是一个动态块它在服务器端渲染不在文章内容中保存 HTML。文章内容中只保存一个块注释block comment例如!-- wp:core/latest-posts {postsToShow:5,displayAuthor:false,displayPostDate:false} /--这正是动态块与静态块的本质区别——当文章被发布后最新文章的标题、日期、作者等信息发生变化时无需重新编辑文章前端输出会自动更新。从 index.php 的注册代码可见register_block_type_from_metadata( __DIR__ . /latest-posts, array( render_callback render_block_core_latest_posts, ) );render_callback指向render_block_core_latest_posts函数负责在请求时生成最终 HTML。二、Attributes 完整属性表源码级解析所有属性通过block.json的attributes属性声明Block API 3 的元数据驱动方式。README 给出了完整表格这里结合 block.json 逐项补充类型校验与默认值细节属性类型默认值说明categoriesarray元素为object—分类过滤每个元素为含id的分类对象可多选selectedAuthornumber—按作者 ID 过滤postsToShownumber5显示文章数量对应posts_per_pagedisplayPostContentbooleanfalse是否显示文章内容displayPostContentRadiostringexcerpt内容显示模式取值excerpt摘要或full_post全文excerptLengthnumber55摘要最大词数displayAuthorbooleanfalse是否显示作者displayPostDatebooleanfalse是否显示发布日期orderstringdesc排序方向asc/descorderBystringdate排序依据date/title等displayFeaturedImagebooleanfalse是否显示特色图片featuredImageAlignstring—图片对齐枚举left、center、rightfeaturedImageSizeSlugstringthumbnail图片尺寸名称如 thumbnail、medium、largefeaturedImageSizeWidthnumbernull自定义图片最大宽度pxfeaturedImageSizeHeightnumbernull自定义图片最大高度pxaddLinkToFeaturedImagebooleanfalse是否给特色图片添加指向文章的链接摘要长度的前后端一致约束摘要长度不是随意数值。前端常量文件 constants.js 定义了硬性边界export const MIN_EXCERPT_LENGTH 10; export const MAX_EXCERPT_LENGTH 100; export const DEFAULT_EXCERPT_LENGTH 55;在编辑器侧edit.jsx中摘要长度由RangeControl控制min与max分别取自MIN_EXCERPT_LENGTH10与MAX_EXCERPT_LENGTH100默认DEFAULT_EXCERPT_LENGTH55。也就是说虽然block.json声明的是通用数值类型但用户界面中合法的取值范围被限定在 10100 之间。三、Supports 支持的编辑能力Supports 控制编辑器提供的样式与控制面板能力同样声明于 block.json。README 汇总如下支持项值说明anchortrue允许设置 HTML 锚点IDaligntrue支持对齐宽、全宽等htmlfalse禁用手动编辑 HTML保证动态输出不被破坏layouttrue支持布局类型列表 / 网格colorgradients: true、link: true支持背景渐变与链接颜色spacingmargin、padding、blockGap边距与块间距blockGap默认1.25emtypographyfontSize、lineHeight字体大小与行高interactivityclientNavigation: true支持客户端导航站点编辑器的 SPA 页面切换需要指出的是实际block.json中 typography 与 border 的能力比 README 表格更丰富typography还启用了__experimentalFontFamily字体族、__experimentalFontWeight字重、__experimentalFontStyle斜体、__experimentalTextTransform、__experimentalTextDecoration、__experimentalLetterSpacing字距且默认控制面板开启fontSizeborder通过__experimentalBorder启用了radius、color、width、style四项color的默认控制面板开启background、text、linkspacing默认开启blockGap。html: false很关键动态块的输出由 PHP 生成允许用户直接编辑 HTML 会导致内容与渲染结果不一致因此被显式关闭。四、服务端渲染index.php 的完整执行流程packages/block-library/src/latest-posts/index.php 是该块的核心逻辑其render_block_core_latest_posts函数完整展示了动态块的执行链路。4.1 查询参数构建渲染的第一步是把块属性映射为WP_Query参数$args array( posts_per_page $attributes[postsToShow], post_status publish, order $attributes[order], orderby $attributes[orderBy], ignore_sticky_posts true, no_found_rows true, );要点说明posts_per_page直接取自postsToShow只查询publish状态的文章ignore_sticky_posts true忽略置顶文章保证排序稳定no_found_rows true跳过分页计数提升性能若设置了categories且为数组则通过array_column( $categories, id )提取 ID 列表并写入category__in若设置了selectedAuthor则写入author参数。分类属性支持多个分类的语义正体现在这里categories是对象数组服务端提取所有id后传入category__in属于任一分类即命中而 index.php 中的block_core_latest_posts_migrate_categories过滤器会把早期版本中“单个分类 ID 字符串”的旧数据自动转换成[ { id: N } ]的新格式。4.2 特色图片缓存if ( isset( $attributes[displayFeaturedImage] ) $attributes[displayFeaturedImage] ) { update_post_thumbnail_cache( $query ); }当开启特色图片显示时提前批量加载所有查询结果的缩略图缓存避免循环内逐个发起数据库查询N1 问题。4.3 循环渲染与全局上下文管理渲染循环使用have_posts()/the_post()而非简单的foreach目的是通过setup_postdata()建立正确的全局$post上下文使得循环内调用的get_permalink()、get_the_title()、get_the_excerpt()等模板标签作用于当前文章。循环开始前对$previous_post做了快照$previous_post $post ?? null;循环结束后代码刻意不使用wp_reset_postdata()而是手动恢复快照并调用setup_postdata( $previous_post )$post $previous_post; if ( $previous_post instanceof WP_Post ) { setup_postdata( $previous_post ); }源码注释解释了原因当该块通过do_blocks()嵌套在另一篇文章内容中渲染时wp_reset_postdata()会错误地恢复到主查询文章而手动恢复才能回到外层渲染上下文。4.4 各显示选项的输出结构循环内每个文章项li的组装顺序为特色图片displayFeaturedImage且has_post_thumbnail()时输出div classwp-block-latest-posts__featured-image align{left|center|right}通过get_the_post_thumbnail( null, $attributes[featuredImageSizeSlug], ... )渲染若设置了featuredImageSizeWidth/featuredImageSizeHeight会生成max-width: Npx;/max-height: Npx;内联样式若开启addLinkToFeaturedImage图片会被a href文章链接 aria-label标题包裹其中 aria-label 使用文章标题以保证无障碍标题a classwp-block-latest-posts__post-title href...无标题时回退为(no title)文案作者displayAuthordiv classwp-block-latest-posts__post-authorby {display_name}/div作者名为空时不输出日期displayPostDatetime datetimeISO 8601 classwp-block-latest-posts__post-datedatetime用get_the_date( c )展示文本用站点日期格式摘要displayPostContent且模式为excerptdiv classwp-block-latest-posts__post-excerpt全文displayPostContent且模式为full_postdiv classwp-block-latest-posts__post-full-content。4.5 摘要长度过滤器与“Read more”链接摘要长度通过过滤器机制生效。渲染开始时$block_core_latest_posts_excerpt_length $attributes[excerptLength]; add_filter( excerpt_length, block_core_latest_posts_get_excerpt_length, 20 );block_core_latest_posts_get_excerpt_length只是返回全局变量值从而让excerpt_length过滤器尊重该块的设置渲染结束后会remove_filter清理避免影响后续内容。关于“Read more”核心wp_trim_excerpt()生成的摘要默认以[hellip;]结尾。源码检测到该结尾时会用substr去掉后 11 个字符即[hellip;]的长度再拼接带无障碍文本的“Read more”链接__( … a classwp-block-latest-posts__read-more href%1$s relnoopenerRead morespan classscreen-reader-text: %2$s/span/a )4.6 全文渲染的递归防护当模式为full_post时代码通过_wp_apply_block_content_filters( $post_content, latest-posts )对原文执行常规内容过滤器。为防止嵌套文章例如最新文章块内部又包含最新文章块造成无限递归源码维护了一个静态渲染栈$rendering_stack若当前文章 ID 已在栈中则直接输出空内容否则入栈渲染并在finally中出栈。4.7 布局类名与列表输出最终输出前依据属性生成一组类名$classes array( wp-block-latest-posts__list ); if ( grid $layout_type ) { $classes[] is-grid; } if ( grid $layout_type ! empty( $column_count ) ) { $classes[] sanitize_title( columns- . $column_count ); } // 开启日期/作者时追加 has-dates / has-author // 设置了链接颜色时追加 has-link-color其中$layout_type优先取layout.type若存在旧属性postLayout grid则回退为grid列数$column_count依次取layout.columnCount或旧属性columns。最终整个列表通过get_block_wrapper_attributes包装为ul %1$s%2$s/ul五、编辑器体验edit.jsx 与查询预览前端编辑逻辑位于 edit.jsx。编辑器内通过wordpress/core-data的getEntityRecords( postType, post, latestPostsQuery )实时预览文章列表查询参数与后端保持一致categories、author、order、orderby、per_page、ignore_sticky并额外请求_embed: author,wp:featuredmedia以获取作者与特色图片的嵌入数据供预览渲染使用。5.1 工具栏与布局切换块上方工具栏BlockControls提供列表视图 / 网格视图切换edit.jsx。切换时会写入layout属性并清空旧属性postLayout与columns即新版统一走layout支持体系。5.2 侧栏控制面板Inspector ControlsControls组件把设置项组织为四个ToolsPanelPost content文章内容显示文章内容开关、内容长度excerpt/full_post单选、最大词数滑杆10100Post meta文章元信息显示作者名、显示文章日期两个开关Featured image特色图片显示特色图片开关、图片尺寸ImageSizeControl可选主题注册的尺寸并自定义宽高、图片对齐ToggleGroupControl无 / 左 / 中 / 右、为特色图片添加链接开关Sorting and filtering排序与筛选使用QueryControls提供排序方向、排序依据、文章数量、分类多选基于分类建议 token 输入与作者筛选。其中分类选择selectCategories的交互值得注意用户输入的 token 必须是已存在的分类建议否则会被拒绝已选分类以对象形式存入categories属性从而与block.json中“对象数组”的类型声明保持一致。5.3 编辑器中的占位与交互保护当没有文章可显示时块显示Placeholder含pin图标与“Latest Posts”标签请求未返回时显示Spinner返回空数组时显示“No posts found.”。由于编辑器内点击链接会跳转离开edit.jsx对所有链接的点击事件都做了preventDefault并弹出 snackbar 警告“Links are disabled in the editor.”。六、废弃版本与迁移机制动态块的迁移不能只依赖编辑器内的 deprecation 机制因为旧数据永远不会被重新编辑。deprecated.js 定义了客户端侧的两代旧格式同时 index.php 通过render_block_data过滤器在服务端兜底迁移。6.1 旧网格布局属性postLayout / columns早期版本使用postLayoutlist/grid与columns默认 3控制布局。新版将这些并入layout支持const migratePostLayout ( oldAttributes ) { const { postLayout, columns, ...attributesWithoutLegacyLayout } oldAttributes; if ( ! postLayout ) { return oldAttributes; } return { ...attributesWithoutLegacyLayout, layout: { type: postLayout grid ? grid : default, ...( postLayout grid columns { columnCount: columns } ), }, }; };6.2 旧分类格式字符串 ID更早期的categories是单个分类 ID 字符串后改为对象数组。迁移函数将其转为[ { id: Number( oldAttributes.categories ) } ]。前端 deprecated.js 与 PHP 端block_core_latest_posts_migrate_categories实现了同样的转换逻辑前者覆盖编辑器加载场景后者覆盖前端渲染场景动态块的内容不会在编辑器中被“保存”回写因此服务端迁移是必须的。6.3 迁移的测试验证单元测试 packages/block-library/src/latest-posts/test/deprecated.jsdom.test.js 验证了迁移的正确性覆盖以下场景postLayout: grid, columns: 4→layout: { type: grid, columnCount: 4 }省略columns时回退默认值 3通过parse()解析旧块注释时触发迁移且postLayout、columns被移除迁移过程中保留textColor、backgroundColor、fontSize、fontFamily及style等块支持属性分类字符串与网格布局可同时迁移categories: 7→[ { id: 7 } ]。七、样式体系style.scss 的结构与命名前台样式位于 packages/block-library/src/latest-posts/style.scssblock.json通过style: wp-block-latest-posts与editorStyle: wp-block-latest-posts-editor分别声明前台与编辑器样式句柄。样式要点列表默认list-style: noneli清除浮动并允许overflow-wrap: break-word旧版网格is-grid:not(.is-layout-grid)走 flex 布局columns-2至columns-6通过 SCSS 循环按百分比计算列宽nth-child清除每行末项的右边距新版原生网格使用layout支持在窄屏$break-small以下将grid-template-columns降为1fr单列日期与作者行使用display: block与0.8125em字号摘要 / 全文容器设置0.5em上边距与1em下边距特色图片支持alignleft左浮动、alignright右浮动与aligncenter居中三种对齐方式图片max-width: 100%、height: auto保证响应式。八、动手实践注册、使用与扩展建议8.1 在文章中使用在编辑器中搜索“最新文章 / Latest Posts / recent posts”插入即可。直接以块注释形式写入内容也是合法的!-- wp:core/latest-posts {postsToShow:3,displayPostDate:true,displayAuthor:true,categories:[{id:5}]} /--8.2 在 PHP 中手动渲染如果你需要在主题中手动渲染该块可调用do_blocks处理块注释或直接构造属性数组调用渲染回调echo render_block_core_latest_posts( array( postsToShow 5, order desc, orderBy date, displayPostDate true, displayAuthor true, displayPostContent false, excerptLength 55, displayFeaturedImage false, ) );注意render_block_core_latest_posts与register_block_core_latest_posts定义在 index.php 中仅当该文件被加载即块已注册时可用。8.3 扩展建议基于源码结构若需自定义查询例如排除特定分类可挂接pre_get_posts或在复制该块的渲染回调后修改WP_Query参数若需改变摘要长度边界注意前后端常量 constants.js10100与block.json需同步调整若需为列表项添加新字段应同时修改 index.php 的渲染回调与 edit.jsx 的预览渲染保证编辑器预览与前台输出一致。九、小结core/latest-posts是理解 Gutenberg 动态块机制的理想样本它以block.json为单一事实来源声明属性与 Supports编辑器侧通过 edit.jsx 提供实时查询预览与分组控制面板服务端通过 index.php 以WP_Query完成查询、缓存、循环渲染、过滤器管理与递归防护前后端协作的 deprecation 与render_block_data迁移保证了历史内容旧网格属性、字符串分类的平滑升级。掌握这一完整链路即可举一反三地理解其他核心动态块如最新评论、文章分类列表的实现模式。【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询