## 是否支持自定义安全策略? 是的。交互式API不使用 [`eval()`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval) 或 [`Function()`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/Function) 构造函数,因此不会违反 [`unsafe-eval`](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy#unsafe_keyword_values) 内容安全策略。该API在设计上可与任何[自定义内容安全策略](https://developer.wordpress.org/apis/security/)协同工作。 ## 能否使用指令发起AJAX/REST-API请求? 当然可以。通过指令调用的操作和回调函数可以执行任何JavaScript函数能实现的功能,包括发起API请求。 ## 交互性API能否在区块之外使用? 当然可以,它不仅限于区块。虽然你会看到许多关于交互性API如何为创建交互式区块提供标准的讨论,但这只是因为那是最常见的用例。更广义地说,交互性API标准可用于为WordPress任何部分的前端添加“交互行为”。 有关在区块外使用任意HTML的交互性API的详细信息,请参阅[`wp_interactivity_process_directives`函数](https://developer.wordpress.org/reference/functions/wp_interactivity_process_directives/)。 ## 这是否意味着我必须将所有交互式区块迁移到此API? 不需要。未使用交互性API的区块可以与使用该API的区块共存。但如前所述,请注意使用该API的区块具有以下优势: - **区块间可轻松通信**:采用标准后,这种通信默认即可实现。当不同区块使用不同方法实现前端交互时,区块间通信会变得复杂,尤其在由不同开发者创建区块时几乎无法实现。 - **可组合性与兼容性**:你可以组合交互式区块,将其嵌套在具有定义行为的结构中,并且由于遵循相同标准,它们完全跨兼容。如果每个区块采用不同的交互方法,很可能会导致功能冲突。 - **减少向浏览器传输的数据量**:如果每个插件作者使用不同的JS框架,前端将加载更多代码。如果所有区块使用同一框架,代码可实现复用。 - 若页面所有区块都采用此标准,则可启用站点级功能(如客户端导航)。 ## 使用此API对性能有何影响?对于非常简单的用例,加载交互性API是否值得? 该API在设计时已充分考虑性能因素: - **指令所需的运行时代码仅约10KB**,且所有区块只需加载一次。 - **所有属于交互性API的脚本模块(包括`view.js`文件)均不会阻塞页面渲染。** - 目前正在[持续探索](https://github.com/WordPress/gutenberg/discussions/52723)**在区块进入视口后延迟加载脚本**的可能性。通过这种方式,可在不影响用户体验的前提下优化初始加载。 ## 是否与核心翻译API兼容? 由于交互性API与服务器端渲染完美配合,你可以使用所有WordPress API,包括[`__()`](https://developer.wordpress.org/reference/functions/__/)和[`_e()`](https://developer.wordpress.org/reference/functions/_e/)。你可以用它翻译HTML中的文本(就像通常做法),甚至可以在[服务器端使用`wp_interactivity_state()`](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/#setting-the-store)时在存储库中使用。示例如下: ```php // render.php wp_interactivity_state( 'favoriteMovies', array( "1" => array( "id" => "123-abc", "movieName" => __("影片名称", "textdomain") ), ) ); ``` 目前正在开发与脚本模块(交互性API所需)兼容的翻译API。请关注[#60234](https://core.trac.wordpress.org/ticket/60234)了解进展。 ## 我担心XSS攻击;JavaScript能否被注入到指令中? 不会。交互性API只允许将[引用](https://developer.wordpress.org/block-editor/reference-guides/interactivity-api/api-reference/#values-of-directives-are-references-to-store-properties)作为值传递给指令。这种方式无需eval()完整的JavaScript表达式,因此不可能实施XSS攻击。 ### 原生 JavaScript 请参阅下方答案。 ### 模板领域特定语言 我们还研究了创建用于编写交互式模板的[领域特定语言](https://en.wikipedia.org/wiki/Domain-specific_language)的可能性。使用该模板DSL编写的代码将被编译为JavaScript和PHP。然而,创建生产级的模板编译器十分复杂,需要投入大量精力且存在较高风险。未来仍会考虑采用这种方案,届时指令系统将作为编译目标。 ## 作为区块开发者,为何应选择交互式API而非React? 在PHP服务端渲染环境中,前端使用React无法流畅运行。所有基于React渲染区块的方案都需通过客户端JavaScript加载内容。若仅通过客户端渲染区块,通常会导致用户体验不佳——用户需要盯着空白占位符和加载动画等待内容呈现。 虽然可通过PHP扩展(如v8js)运行JS,但遗憾的是PHP扩展不具向后兼容性,且必须存在PHP降级方案时才能使用。 当前虽可实现在PHP中服务端渲染区块,并同时在前端使用React渲染相同区块,但这会导致开发体验恶化——相同逻辑需在PHP和React部分重复实现。更严重的是,您将面临WordPress钩子引发的隐蔽错误! 假设安装的第三方插件通过钩子(过滤器)修改了服务端渲染的HTML,例如为区块HTML添加单个CSS类。该CSS类会存在于服务端渲染的标记中。但在前端,您的区块通过React重新渲染时,由于无法对React渲染内容应用WordPress钩子,最终呈现的内容将缺失这个CSS类! 反观交互式API,其设计理念是通过指令为服务端渲染的HTML增强交互行为,因此能与WordPress钩子完美协同。这也意味着它可以开箱即用地兼容WordPress后端API(如i18n)。 总结而言,选择交互式API而非单纯使用React具有以下优势: - 使用React时,交互式区块在客户端生成的标记必须与服务端PHP生成的完全一致。而交互式API无此限制,指令可直接附加于服务端渲染的HTML - 交互式API对PHP更友好,可无缝兼容WordPress钩子及其他服务端功能(如国际化)。例如使用React时,您无法预知服务端应用的钩子,其修改效果将在水合后被覆盖 - 具备[采用标准化方案](/docs/reference-guides/interactivity-api/iapi-about.md#why-a-standard)的所有优势 ## 与jQuery或原生JavaScript相比,交互式API的优势何在? 核心差异在于交互式API具备**声明式与响应式特性**,这使得编写和维护复杂交互体验变得更为轻松。此外,它**专为区块开发量身定制**,提供的标准规范具备前述各项优势,包括区块间通信、兼容性以及客户端导航等全站功能。 最后与jQuery对比:**交互式API运行时仅约10kb**,体积更轻量化。实际上,WordPress生态正在持续推进移除jQuery等重型框架的工作,本API将为此提供助力。 ## 是否需要同时掌握React、PHP和本交互式API? 若希望使用本API为区块添加前端交互功能,简短答案是肯定的。如果区块无需交互功能,区块创建流程将完全保持不变。 交互式API引入了新的标准方法,以简化WordPress前端交互行为的集成。这意味着您仍需要使用React来处理区块的编辑器部分。 反之,若要创建交互式区块,采用交互式API后您无需处理复杂议题,例如工具链配置、WordPress集成、区块间通信或交互部件的服务端渲染。 # 常见问题解答 ## 交互性 API 底层是如何运作的? 其三大核心组件包括: - 采用 [Preact](https://preactjs.com/) 与 [Preact Signals](https://preactjs.com/guide/v10/signals/) 组合实现水合作用、客户端逻辑及客户端导航功能 - 可被客户端与服务端共同解析的 HTML 指令系统 - 由 [HTML 标签处理器](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2/) 处理的服务器端逻辑 ## 为何选择 Preact 构建指令系统?为何不采用 React 或其他 JavaScript 框架? 在前端应用场景中(这也是交互性 API 的核心定位),Preact 相较于 React 及 Vue、Svelte、Solid 等框架具有显著优势: - 体积轻量:包含 [钩子函数](https://preactjs.com/guide/v10/hooks/) 与 [信号系统](https://preactjs.com/blog/introducing-signals/) 仅 8kB - 开箱即用的 DOM 差异化比较功能 - 通过可选钩子实现高度可扩展性,该特性被广泛应用于钩子函数、React 兼容层 (preact/compat) 及信号系统 (@preact/signals),覆盖除 DOM 差异算法外的所有功能模块 - 核心团队技术实力雄厚且提供强力支持,并对 Preact 的“孤岛架构”应用模式表现出浓厚兴趣 ## Gutenberg 编辑器是否会因交互性 API 采用 Preact 而从 React 迁移? 不会。目前暂无迁移计划。作为一个完全交互式应用,编辑器的功能需求与优势考量存在显著差异。虽然 Preact 提供完全兼容 React 生态的 [`@preact/compat`](https://preactjs.com/guide/v10/switching-to-preact/) 套件,且已被众多大型网络应用采纳,但在区块编辑器中使用 Preact 无法获得像交互性 API 在前端场景中的同等优势。 ## 除指令系统外,还考虑过哪些替代方案? 我们曾评估多种替代方案,以下是部分方案的简要概述: ### React 及其他 JavaScript 框架 由于 Gutenberg 开发者对 React 更熟悉,该框架成为首要考量对象。其他主流 JS 框架如 Svelte、Vue.js 或 Angular 也在评估之列,但这些框架(包括 React)均存在与 PHP 环境兼容性不足、无法适配 WordPress 钩子系统或国际化需求的局限性。 ### Alpine.js Alpine.js 是优秀的框架方案,其诸多功能设计为交互性 API 带来重要启发。但该框架不支持服务端渲染 [指令](https://github.com/alpinejs/alpine/tree/d7f9d641f7a763c56c598d118bd189a406a22383/packages/docs/src/en/directives),而为 WordPress 区块量身打造专属系统能带来更多收益。 最终选择 Preact 取代 Alpine.js 基于多重考量:更小的体积尺寸、更优的性能表现(特别是集成 [信号系统](https://preactjs.com/guide/v10/signals/) 后)、基于 Preact 声明式语法及工具链(钩子、信号)编写自定义指令、相比 Alpine.js 具有更充分的实战检验与更庞大的开发者社区。同时完美兼容 React(便于共享编辑器中的客户端渲染组件),并为交互性 API 提供开箱即用的最快 DOM 差异算法,包含 UI 状态保持功能。 更重要的是,依托 Preact 的底层支撑,交互性 API 可专注管理“最终呈现层”,从而更好适配 WordPress 的特殊需求。例如:为避免安全风险并确保符合严格的安全策略,指令内部禁止使用 JavaScript 表达式;所有 WordPress 指令均符合 HTML 属性规范标准。
欢迎查阅 《为何选择 Preact 而非 Alpine?》 专题讨论获取更多信息。