ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Gutenberg Block API Versions:从 apiVersion 1 到 3 的 useBlockProps 机制与 iframe 文章编辑器演进

Gutenberg Block API Versions:从 apiVersion 1 到 3 的 useBlockProps 机制与 iframe 文章编辑器演进 Gutenberg Block API Versions从 apiVersion 1 到 3 的 useBlockProps 机制与 iframe 文章编辑器演进【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg本文以 Gutenberg 仓库中 Block API Versions 参考文档 为主体完整梳理 Block API 三个版本1、2、3的变更内容Version 2 引入的useBlockProps()序列化契约、Version 3 引入的 iframe 文章编辑器及其在各 WordPress/Gutenberg 版本中的生效条件。读完本文你不仅能理解apiVersion字段在注册与序列化流程中的实际作用有源码为证还能按照配套的 iframe 编辑器兼容迁移指南 完成区块测试与迁移包括ownerDocument/defaultView的写法、第三方库的适配与打补丁流程。三个版本的总览Gutenberg 仓库中的 API Versions 文档将 Block API 划分为三个版本每个版本对应一组必须满足的行为契约版本引入时间核心变更Version 1初始版本Block API 的初始形态Version 2WordPress 5.61.edit实现必须通过useBlockProps()钩子渲染区块元素包裹层block element wrapper2. 对静态区块static blockssave执行时不再自动把生成的类名和样式追加到保存的标记中作者必须显式调用useBlockProps.save()并展开到区块包裹层上Version 3WordPress 6.3区块必须能在 iframe 中正常工作Version 2 的两条契约本质上都是把区块包裹层的控制权交还给作者编辑端和保存端的class、style、ref等属性都由作者通过钩子显式声明Block API 不再隐式替作者决定。下面结合源码说明这两条契约在实现层是如何落地的。Version 2useBlockProps 契约在序列化管线中的体现edit 端useBlockProps() 提供区块元素包裹层从 Version 2 起edit组件若要让编辑器为区块生成带正确类名、内联样式和选择高亮的元素包裹层必须使用useBlockProps()钩子并将返回的 props 展开到根元素上。这是 Gutenberg 中几乎所有区块Edit组件的标准写法import { useBlockProps } from wordpress/block-editor; export default function Edit() { const blockProps useBlockProps(); return div { ...blockProps }Hello world!/div; }save 端v2 及以上版本跳过 getSaveContent.extraProps 过滤器Version 2 的另一条契约——生成的类名和样式不再自动加入保存标记——可以直接在序列化源码中得到印证。在 区块序列化实现 中save函数执行完毕后只有当区块的apiVersion不大于 1 时才会应用blocks.getSaveContent.extraProps过滤器把额外 props 合并进保存结果元素if ( element ! null typeof element object hasFilter( blocks.getSaveContent.extraProps ) ! ( ( blockType.apiVersion ?? 0 ) 1 ) ) { const props applyFilters( blocks.getSaveContent.extraProps, { ...element.props }, blockType, attributes ); // ... 若 props 有变化则 cloneElement 合并 }也就是说v1 区块在保存时仍会享受自动补充包裹层属性的旧行为而 v2 及以上的区块完全依赖作者自行调用useBlockProps.save()生成包裹层属性export function save() { return ( div { ...useBlockProps.save() } Hello world! /div ); }这正是文档中区块作者必须显式使用useBlockProps.save()并添加到区块包裹层的底层原因序列化管线对高版本区块主动关闭了自动补全路径。Version 3区块必须能在 iframe 中工作Version 3 的全部含义浓缩为文档中的一句话Adding version 3 support means that a block should work inside an iframe.添加 Version 3 支持意味着区块应当能在 iframe 内正常运行。之所以以 iframe 作为分界线是因为 Gutenberg 正在把文章编辑器迁入 iframe而apiVersion是编辑器判断区块是否就绪的信号。iframe 文章编辑器的技术收益迁移指南列出了 iframe 编辑器带来的关键收益样式隔离后台Admin样式不再影响编辑器内容无需重置 admin CSS 规则内容样式也不再影响后台页面区块和主题的 CSS 规则无需再加前缀视口相对单位vw、vh能正确工作。没有 iframe 时这些单位是相对于整个后台页面而非编辑器内容区域媒体查询原生可用不再需要脆弱的变通方案开发更简单前端的样式几乎可以原样落到编辑器中对轻量区块lighter blocks编辑器 DOM 结构与前端的 DOM 结构一致尤其如此选择处理编辑器内容有了独立的 window可以在编辑器内容中保持可见文本选区的同时在编辑器 UI 中另有一个收起状态的选区例如 URL 输入框。iframe 生效条件在各版本中的演进文档与迁移指南共同勾勒出一条清晰的时间线理解它有助于判断我的区块现在跑在 iframe 里吗WordPress 6.3Version 3 引入当所有已注册区块都使用 Block API version 3 及以上、且不存在传统 meta box时WordPress 6.3 启用 iframe 化的文章编辑器。注意此时判断范围是所有注册区块任何一个 v2 区块都会拖住整个编辑器。WordPress 6.9开始推动开发者提前测试——对以apiVersion2 或更低注册的区块在浏览器控制台发出警告并把 block.json schema 更新为只允许apiVersion: 3。这一点在仓库源码中有两处直接印证block.json schema 中apiVersion字段定义为type: integer, const: 3即 schema 层面当前只接受 3描述中也提示 v2 及以下区块可能导致文章编辑器以非 iframe 模式工作processBlockType 实现 中区块注册处理逻辑检测到settings.apiVersion 2时即调用deprecated( Block with API version 2 or lower, { since: 6.9, ... } )提示内容正是请设置apiVersion为 3 并在 iframe 编辑器中测试区块。注册测试用例 也验证了未显式声明apiVersion的区块默认按版本 1 处理并会触发这条弃用警告。同时processBlockType 的合并逻辑表明未在block.json或注册参数中声明apiVersion的区块默认值为1apiVersion: 1这也是老区块会收到弃用警告的原因。WordPress 7.0判断 iframe 的条件从所有已注册区块收窄为实际出现在文章内容中的区块。即只要文章内容里不存在apiVersion2 或更低的区块编辑器就用 iframe保留的非 iframe 回退路径由useShouldIframe钩子决定迁移指南中引用了该钩子在历史提交cd4fae71中的位置packages/edit-post/src/components/layout/use-should-iframe.js。具体条件是Gutenberg 插件启用时编辑器始终以 iframe 工作插件未启用时满足以下任一条件即使用 iframe——设备类型不是Desktop如平板/手机预览、当前文章类型是wp_template或wp_block、放大模式zoom-out mode激活、或文章内容中所有区块均为apiVersion3 及以上。文档同时强调这是一条临时兼容路径——启用 Gutenberg 插件时它不生效并计划在 WordPress 7.1 中移除。Gutenberg 23.6 与 WordPress 7.1无条件使用 iframe。条件回退被移除文章内容区块的apiVersion是多少都不再影响编辑器形态。从当前仓库源码结构可以印证这一点packages/edit-post/src/components/layout/目录下已不存在use-should-iframe.js文件layout 组件 中也不再引用该钩子与Gutenberg 当前 trunk 恒用 iframe的描述一致。在 iframe 编辑器中测试你的区块所有核心区块已经使用apiVersion3。文档建议的测试路径是最简单的方式是启用Gutenberg 23.6 或更高版本此时文章编辑器恒为 iframe来验证区块行为测试通过后再把区块的apiVersion提升到 3。在 WordPress 7.0 且未启用 Gutenberg 插件的环境下若文章含有apiVersion2 或更低的区块编辑器会回退到非 iframe 模式不适合用于验证。迁移实战让区块在 iframe 中正确工作大多数区块无需改动即可运行但文档明确列出几类需要注意的技术点迁移指南给出了逐一可复制的解决方案。document 与 window 不再指向内容所在环境iframe 拥有与后台页面现在是父窗口不同的document和window。编辑器脚本加载在后台页面中因此直接操作全局document/window来影响区块内容的代码将失效。用 React 编写的区块大多不受影响除非依赖了全局对象修复方式是借助元素引用拿到内容所在的 documentownerDocument和 windowdefaultView——无论是否使用 iframe这都是良好实践。使用 useRef 获取 ownerDocumentimport { __ } from wordpress/i18n; import { useBlockProps } from wordpress/block-editor; import { useRef, useEffect } from wordpress/element; export default function Edit() { const ref useRef(); useEffect( () { const { ownerDocument } ref.current; const { defaultView } ownerDocument; defaultView.addEventListener( ... ); return () { defaultView.removeEventListener( ... ); }; }, [] ); const blockProps useBlockProps( { ref } ); return ( div { ...blockProps } Hello world! /div ); }使用 useRefEffect推荐由于useEffect在 ref 变化时不会重新执行回调迁移指南推荐使用useRefEffectAPI——它在 ref 变化时以及依赖项变化时都会调用回调import { __ } from wordpress/i18n; import { useBlockProps } from wordpress/block-editor; import { useRefEffect } from wordpress/compose; export default function Edit() { const ref useRefEffect( ( element ) { const { ownerDocument } element; const { defaultView } ownerDocument; defaultView.addEventListener( ... ); return () { defaultView.removeEventListener( ... ); }; }, [] ); const blockProps useBlockProps( { ref } ); return ( div { ...blockProps } Hello world! /div ); }第三方框架与库传入元素引用而非依赖全局jQuery 等脚本加载在父窗口后台页面中用它操作 iframe 内区块时应传入元素引用import { useRefEffect } from wordpress/compose; import jQuery from jquery; export default function Edit() { const ref useRefEffect( ( element ) { jQuery( element ).masonry( … ); return () { jQuery( element ).masonry( destroy ); }; }, [] ); const blockProps useBlockProps( { ref } ); return ( div { ...blockProps }Hello world!/div ); }如果某个不受你控制的库内部使用了全局window/document两条路一是向上游提交 issue/PR 让其改用ownerDocument/defaultView理想情况下任何库都应支持以 iframe 内元素为初始化目标二是临时使用加载在 iframe 内部的脚本——Gutenberg 已把前端脚本同时加载进 iframe 以覆盖这类场景可通过defaultView访问并需处理脚本异步加载未加载时直接返回依赖加载完成后区块会重新渲染export default function Edit() { const ref useRefEffect( ( element ) { const { ownerDocument } element; const { defaultView } ownerDocument; // 脚本异步加载先确认其已就绪。 if ( ! defaultView.jQuery ) { return; } defaultView.jQuery( element ).masonry( … ); return () { defaultView.jQuery( element ).masonry( destroy ); }; } ); const blockProps useBlockProps( { ref } ); return div { ...blockProps }Hello world!/div; }打补丁patch-package 工作流等不到上游修复时可以用 patch-package 自行打补丁并纳入版本控制以 npm 和panzoom/panzoom为例直接编辑node_modules中的库代码把全局document/window替换为由区块元素派生的ownerDocument/defaultView例如编辑node_modules/panzoom/panzoom/dist/panzoom.es.js安装 patch-packagenpm add -D patch-package为库生成补丁npm exec --no -- patch-package panzoom/panzoom在package.json中加入postinstall脚本使补丁在每次安装后自动应用scripts: { postinstall: patch-package }把生成的.patch文件位于patches目录和更新后的package.json一并提交版本控制。生成的补丁典型形态是把全局引用替换为元素的ownerDocument例如panzoom/panzoom的补丁function isAttached(node) { var { ownerDocument } node; var currentNode node; while (currentNode currentNode.parentNode) { - if (currentNode.parentNode document) if (currentNode.parentNode ownerDocument) return true; currentNode currentNode.parentNode instanceof ShadowRoot function Panzoom(elem, options) { bound true; var { ownerDocument } elem; onPointer(down, options.canvas ? parent : elem, handleDown); - onPointer(move, document, handleMove, { passive: true }); - onPointer(up, document, handleUp, { passive: true }); onPointer(move, ownerDocument, handleMove, { passive: true }); onPointer(up, ownerDocument, handleUp, { passive: true }); }即使打补丁可行也建议提交上游 issue/PR让库原生支持 iframe 环境。值得一提的是Gutenberg 仓库自身的patches/目录含 patch 说明正是这一工作流在 monorepo 层面的实际运用。版本选择速查与结论综合文档与仓库源码可以为区块开发者给出如下决策依据场景建议的 apiVersion历史遗留区块、尚未测试 iframe保持现状但注意自 6.9 起注册时会触发弃用警告schema 已不再接受非 3 值常规新区块直接在block.json中声明apiVersion: 3并按本文的ownerDocument/useRefEffect模式排查对全局document/window的依赖在 Gutenberg 23.6 或 WordPress 7.1 环境编辑器恒为 iframeapiVersion不再影响编辑器形态但 3 仍是唯一被 schema 接受的值三句话总结这条演进线Version 2WordPress 5.6把区块包裹层的渲染权交还给作者useBlockProps()/useBlockProps.save()序列化管线对 v2 区块关闭了getSaveContent.extraProps自动补全见 serializer.tsxVersion 3WordPress 6.3把能在 iframe 中工作设为区块契约驱动文章编辑器从全部注册区块就绪才启用6.3、文章内容区块就绪才启用7.0最终走向无条件启用Gutenberg 23.6 / WordPress 7.1。apiVersion不只是一个数字字段它是 Gutenberg 向 iframe 化编辑器迁移过程中的能力声明与兼容性开关。【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表