gutenbergdocs/docs/reference-guides/interactivity-api/iapi-faq.md
2025-10-22 01:40:18 +08:00

133 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 是否支持自定义安全策略?
是的。交互式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 属性规范标准。
<div class="callout callout-info">
欢迎查阅 <a href="https://github.com/WordPress/gutenberg/discussions/53022#discussioncomment-4696611">《为何选择 Preact 而非 Alpine</a> 专题讨论获取更多信息。
</div>