资讯动态

Gutenberg 块目录数据存储 core/block-directory 完全指南:Selectors 与 Actions 源码级解析

发布时间:2026/9/17 7:48:20 来源:尧图企业网站定制
Gutenberg 块目录数据存储 core/block-directory 完全指南Selectors 与 Actions 源码级解析【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg本文是 Gutenberg 项目core/block-directory数据存储data store的深度技术指南。它对应 docs/reference-guides/data/data-core-block-directory.md 中自动生成的 API 参考在此基础上结合 packages/block-directory 包的真实源码完整讲解该存储的 8 个 Selectors、10 个 Actions、底层 Resolver 与 Reducer 的 state 结构并串联起在块插入器中搜索 WordPress.org 块 → 一键安装并注入到文章 → 保存时自动卸载未使用块的完整工作流。读完本文你将能够熟练使用wp.data.select( core/block-directory )与wp.data.dispatch( core/block-directory )驱动块目录功能并理解其背后的实现原理。一、Block directory 包与数据存储定位wordpress/block-directory是 Gutenberg 中用于扩展块编辑器、提供从 WordPress.org 搜索并安装块能力的包。其 README 明确指出该包构建为一个独立 JS 文件当页面加载了块编辑器时它通过__unstableInserterMenuExtension这一 slot-fill 挂载点接入块类型列表当用户搜索且本地没有匹配结果时它会向 WordPress.org 发起请求把匹配到的块列出来供用户一键安装——安装、激活并注入到当前文章中。这个数据存储的注册入口在 packages/block-directory/src/store/index.js核心代码只有寥寥数行const STORE_NAME core/block-directory; export const storeConfig { reducer, selectors, actions, resolvers, }; export const store createReduxStore( STORE_NAME, storeConfig ); register( store );也就是说core/block-directory是一个标准的 Gutenberg 数据存储由wordpress/data的createReduxStore创建并register注册由reducer、selectors、actions、resolvers四部分构成分别位于packages/block-directory/src/store/reducer.jspackages/block-directory/src/store/selectors.jspackages/block-directory/src/store/actions.jspackages/block-directory/src/store/resolvers.jsState 结构由 reducer.js 的combineReducers可以看出该存储的全局 state 由三个子 state 组成export default combineReducers( { downloadableBlocks, blockManagement, errorNotices, } );downloadableBlocks以搜索词filterValue为键的对象每个键对应{ isRequesting: boolean, results: Array }存放可下载未安装块的搜索结果blockManagement{ installedBlockTypes: Array, isInstalling: {} }installedBlockTypes记录本次会话中已安装的块isInstalling以块 ID 为键记录安装中的状态errorNotices以块 ID 为键的错误通知对象值为{ message, isFatal }。二、Selectors 详解所有 Selectors 都可通过wp.data.select( core/block-directory )访问参数与返回值以 docs/reference-guides/data/data-core-block-directory.md 为准实现细节参考 selectors.js。2.1 isRequestingDownloadableBlocks( state, filterValue )返回指定搜索词是否正在请求可下载块。参数state全局状态Object、filterValue搜索字符串string返回boolean——该搜索词对应的请求是否在进行中实现state.downloadableBlocks[ filterValue ]?.isRequesting ?? false未发起过请求时返回false。2.2 getDownloadableBlocks( state, filterValue )返回可下载未安装的块列表。参数state、filterValue返回Array——可下载块数组实现state.downloadableBlocks[ filterValue ]?.results ?? EMPTY_ARRAY其中EMPTY_ARRAY是模块级常量避免每次返回新数组引发不必要的重渲染。2.3 getInstalledBlockTypes( state )返回本次会话中已在服务器上安装的块类型。参数state返回Array——块类型条目实现直接返回state.blockManagement.installedBlockTypes。2.4 getNewBlockTypes( state )返回已在服务器上安装且在当前文章中正在使用的块类型。参数state返回Array——块类型条目实现说明这是一个createRegistrySelectorcreateSelector组合选择器。它从 block-editor 存储读取getBlockName与getClientIdsWithDescendants取出当前文章所有块含嵌套子块的名称与installedBlockTypes的名称集合取交集见 selectors.js。这用于发布前面板Pre-Publish Panel向用户展示本次会话中新安装并被实际使用的块。2.5 getUnusedBlockTypes( state )返回已在服务器上安装但当前文章中未使用的块类型。参数state返回Array——块类型条目实现说明与getNewBlockTypes同构但做的是差集运算——从installedBlockTypes中过滤掉当前文章用到的块名见 selectors.js。它是自动卸载机制的核心数据来源保存文章时未被使用的块会被静默卸载避免编辑器被无用的插件堆积。2.6 isInstalling( state, blockId )返回指定块当前是否正在安装中。参数state、blockId块的 IDstring如my-block返回boolean实现state.blockManagement.isInstalling[ blockId ] || false。2.7 getErrorNotices( state )返回全部块错误通知。参数state返回Object——错误通知对象以块 ID 为键。2.8 getErrorNoticeForBlock( state, blockId )返回指定块的错误通知。参数state、blockId返回string|boolean——错误文本若无错误则返回false实现state.errorNotices[ blockId ]该键不存在时返回undefined文档将其约定为false 即无错误的语义。三、Actions 详解所有 Actions 都可通过wp.data.dispatch( core/block-directory )访问。其中纯 action creator 返回带type的动作对象而installBlockType、uninstallBlockType是带副作用的 thunk action。实现参考 actions.js。3.1 fetchDownloadableBlocks( filterValue )返回{ type: FETCH_DOWNLOADABLE_BLOCKS, filterValue }用于标记某搜索词的可下载块正在加载。对应 reducer 将downloadableBlocks[ filterValue ]置为{ isRequesting: true }。3.2 receiveDownloadableBlocks( downloadableBlocks, filterValue )返回{ type: RECEIVE_DOWNLOADABLE_BLOCKS, downloadableBlocks, filterValue }用于接收搜索结果。对应 reducer 将结果写入results并置isRequesting: false。3.3 installBlockType( block )触发安装一个块插件是整个存储中最核心的 action参数block搜索返回的块条目对象Object返回boolean——块是否成功安装并加载。其内部流程actions.js值得逐段拆解清理旧错误并标记安装中dispatch.clearErrorNotice( id )然后dispatch.setIsInstalling( id, true )。判断插件是否已安装但未激活通过 get-plugin-url.js 从block.links[wp:plugin]优先级高于block.links.self取出插件 API 链接。若存在wp:plugin链接说明插件已安装只是未激活此时用apiFetch发送PUT请求把status置为active否则说明尚未安装发送POST wp/v2/plugins携带{ slug: id, status: active }完成安装并激活同时从响应中取出_links合并回块对象。记录已安装块dispatch.addInstalledBlockType( { ...block, links: { ...block.links, ...links } } )。引导服务器端块元数据向/wp/v2/block-types/${ name }请求_fields白名单中的元数据字段api_version、title、category、attributes、supports、variations、block_hooks等 18 个字段随后调用unstable__bootstrapServerSideBlockDefinitions把这些元数据注入编辑器见 actions.js。请求失败如块尚未在服务端注册会被.catch( () {} )静默忽略。加载块资源调用loadAssets()见下文第五节。校验注册结果从wordpress/blocks存储读取已注册块类型若其中找不到name抛出Error( Error registering block. Try reloading the page. )。成功通知通过wordpress/notices的createInfoNotice弹出 snackbar 提示 Block %s installed and added.。错误处理setErrorNotice( id, message, isFatal )写入存储同时createErrorNotice弹出可关闭的错误通知。对于无法恢复的错误自定义异常以及folder_exists、unable_to_connect_to_filesystem两种致命 API 错误isFatal会被置为true对应文案分别为该块已安装请尝试刷新页面与安装块时出错可刷新页面重试见 actions.js。无论成败最后都会dispatch.setIsInstalling( id, false )并返回success布尔值。3.4 uninstallBlockType( block )触发卸载一个块插件actions.js从块对象取得wp:pluginAPI 链接PUT把插件status置为inactiveDELETE删除插件dispatch.removeInstalledBlockType( block )从已安装跟踪列表移除出错时通过 notices 存储弹出错误通知。3.5 addInstalledBlockType( item )返回{ type: ADD_INSTALLED_BLOCK_TYPE, item }把块条目追加到installedBlockTypes跟踪列表。item为带块 id 与 name 的块对象。3.6 removeInstalledBlockType( item )返回{ type: REMOVE_INSTALLED_BLOCK_TYPE, item }从跟踪列表移除块。reducer 按blockType.name ! action.item.name过滤。3.7 setIsInstalling( blockId, isInstalling )返回{ type: SET_INSTALLING_BLOCK, blockId, isInstalling }更新isInstalling状态表。3.8 setErrorNotice( blockId, message, isFatal false )返回{ type: SET_ERROR_NOTICE, blockId, message, isFatal }写入或覆盖指定块的错误通知。isFatal表示用户是否无法从错误中恢复。3.9 clearErrorNotice( blockId )返回{ type: CLEAR_ERROR_NOTICE, blockId }清空指定块的错误通知。reducer 通过解构从 state 中删除该键case CLEAR_ERROR_NOTICE: const { [ action.blockId ]: blockId, ...restState } state; return restState;四、Resolvers 与搜索数据流Resolvers 是 Gutenberg 数据层的自动数据加载机制当组件调用尚未有数据的 Selector 时对应 Resolver 会自动触发。本存储只有一个 Resolver——getDownloadableBlocksresolvers.jsexport const getDownloadableBlocks ( filterValue ) async ( { dispatch } ) { if ( ! filterValue ) { return; } try { dispatch( fetchDownloadableBlocks( filterValue ) ); const results await apiFetch( { path: wp/v2/block-directory/search?term${ filterValue }, } ); const blocks results.map( ( result ) Object.fromEntries( Object.entries( result ).map( ( [ key, value ] ) [ camelCase( key ), value, ] ) ) ); dispatch( receiveDownloadableBlocks( blocks, filterValue ) ); } catch { dispatch( receiveDownloadableBlocks( [], filterValue ) ); } };值得注意的细节空搜索词短路filterValue为空时直接返回不发请求底层 APIwp/v2/block-directory/search?term${ filterValue }对应 README 中提到的 WordPress.org 搜索端点键名驼峰化服务端返回的 snake_case 键如block_name、author_block_count会被change-case的camelCase统一转换为 camelCase如blockName保证前端代码风格一致失败兜底请求异常时接收空数组避免 UI 卡在加载态。五、块资源加载loadAssets 机制安装块后编辑器需要加载该块所需的 CSS/JS。这部分由 packages/block-directory/src/store/load-assets.js 完成其思路非常巧妙loadAssets()通过apiFetch请求当前页面 URL即post-new.php或post.php?post1actionedit并把响应按 HTML 文本解析用DOMParser解析出响应中的所有link[relstylesheet]与script元素过滤掉document中已存在的按asset.id去重得到新增资源按顺序逐个loadAsset因为后续脚本可能依赖先前加载的脚本。loadAsset( el )会重建元素节点直接插入原节点不一定触发onload复制id/rel/src/href/type属性并保留内联脚本内容然后追加到document.body对于link样式表和无src的内联脚本插入后立即 resolve无需等待加载完成见 load-assets.js。文件注释也指出未来可以改进为依赖block.json或 script-loader 依赖 API从而不必比较页面资源差异。六、完整工作流搜索 → 安装 → 使用 → 自动卸载上述 API 最终被组织成三个插件 UI统一在 packages/block-directory/src/plugins/index.jsx 中通过registerPlugin( block-directory, ... )注册并通过addFilter( blocks.registerBlockType, ... )接管core/missing缺失块的编辑体验。整个工作流可以串成一条完整链路6.1 在插入器中搜索InserterMenuDownloadableBlocksPanel 通过__unstableInserterMenuExtension接收插入器的filterValue搜索词用 400ms 防抖后传给DownloadableBlocksPanel。当插入器里没有本地匹配块hasLocalBlocks为 false时面板展示来自 WordPress.org 的搜索结果。搜索词一旦变化就会通过 Resolver 自动触发getDownloadableBlocks进而驱动上述wp/v2/block-directory/search请求UI 上以isRequestingDownloadableBlocks控制加载状态。6.2 一键安装并注入文章搜索结果列表项上的安装按钮install-button.jsx调用installBlockType( block ).then( ( success ) { if ( success ) { const blockType getBlockType( block.name ); const [ originalBlock ] parse( attributes.originalContent ); if ( originalBlock blockType ) { replaceBlock( clientId, createBlock( blockType.name, originalBlock.attributes, originalBlock.innerBlocks ) ); } } } );即安装成功后将缺失块占位内容attributes.originalContent重新解析为真实块并用replaceBlock替换到当前编辑位置——这就是 README 中installs, activates, and injects the block into the post的一键注入。按钮在安装期间由isInstalling( block.id )驱动为disabled与isBusy状态。6.3 发布前面板展示新块InstalledBlocksPrePublishPanel 在发布前使用getNewBlockTypes()列出本次会话新安装且被当前文章使用的块提示用户这些块会在保存后随文章一并生效。6.4 保存时自动卸载未使用的块AutoBlockUninstaller 监听编辑器的保存状态当isSavingPost()为 true 且isAutosavingPost()为 false即真实保存而非自动保存时读取getUnusedBlockTypes()对每个未使用的块依次执行uninstallBlockType( blockType )走第三节的卸载 action并unregisterBlockType( blockType.name )注销其类型定义。这就是 README 所说的 When the post is saved, if the block was not used, it will be silently uninstalled to avoid clutter——避免用户为一次性使用而留下永久插件。七、测试与验证该存储的 Selectors 与 Actions 均有配套单元测试可作为理解 API 行为的最佳范例packages/block-directory/src/store/test/selectors.jsdom.test.js覆盖全部 8 个 Selector。例如isRequestingDownloadableBlocks测试验证无请求记录返回 false、无挂起请求返回 false、有挂起请求返回 true三种状态getNewBlockTypes/getUnusedBlockTypes测试则通过blockListIds、blockTypeInstalled、blockTypeUnused等 fixture 验证已安装且使用中与已安装但未使用的集合运算逻辑。packages/block-directory/src/store/test/actions.jsdom.test.js验证installBlockType的完整调用序列apiFetch参数、setIsInstalling状态翻转、notices 的创建以及uninstallBlockType的PUT/DELETE流程。packages/block-directory/src/store/test/reducer.js验证三个 reducer 对各类 action 的纯函数状态转换。packages/block-directory/src/store/test/load-assets.jsdom.test.js验证loadAsset的资源注入行为。UI 组件层也有快照与行为测试例如 downloadable-block-icon、downloadable-block-list-item、downloadable-blocks-list 下的test/目录。八、开发集成小结要在自己的项目中使用该数据存储按 README 安装即可npm install wordpress/block-directory --save该包假设运行环境为ES2015若目标环境对语言特性支持有限需引入wordpress/babel-preset-default自带的 polyfill。使用方式上读取状态wp.data.select( core/block-directory )下的 8 个 Selectors搜索块、安装状态、错误通知、已安装/新安装/未使用块派发动作wp.data.dispatch( core/block-directory )下的 10 个 Actions发起搜索、接收结果、安装/卸载块、跟踪安装状态、管理错误通知。九、总结core/block-directory虽小却是块编辑器按需获取块能力的关键数据中枢它用一个精炼的 Redux store3 个 reducer、8 个 selectors、10 个 actions、1 个 resolver完整承载了从 WordPress.org 搜索块、一键安装激活、服务端元数据引导、资源加载、使用跟踪到保存时自动卸载的全生命周期。理解它的 Selectors 与 Actions不仅能让你熟练调用块目录能力也为阅读其他 Gutenberg 数据存储如core/editor、core/block-editor提供了可复用的方法论。【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价