## 服务器端函数 Interactivity API 提供了一系列便捷函数,使您能够在服务器端初始化和引用配置选项。这对于提供初始数据至关重要,服务器端指令处理将利用这些数据在 HTML 标记发送到浏览器前对其进行修改。这也是充分利用 WordPress 诸多 API(如随机数验证、AJAX 和翻译功能)的绝佳方式。 ### wp_interactivity_config `wp_interactivity_config` 用于设置或获取与存储命名空间关联的配置数组。 该配置在客户端也可用,但属于静态信息。 可将其视为网站交互的全局设置,这些设置不会随用户交互而更新。 设置示例: ```php wp_interactivity_config( 'myPlugin', array( 'showLikeButton' => is_user_logged_in() ) ); ``` 获取示例: ```php wp_interactivity_config( 'myPlugin' ); ``` 此配置可在客户端获取: ```js // view.js const { showLikeButton } = getConfig(); ``` ### wp_interactivity_state `wp_interactivity_state` 用于在服务器端初始化全局状态,该状态将用于处理服务器端指令,随后会与客户端定义的任何全局状态合并。 在服务器端初始化全局状态还允许您使用许多关键的 WordPress API,包括 [AJAX](https://developer.wordpress.org/plugins/javascript/ajax/) 或 [随机数验证](https://developer.wordpress.org/plugins/javascript/enqueuing/#nonce)。 `wp_interactivity_state` 函数接收两个参数:一个用作引用标识的命名空间字符串,以及一个包含值的关联数组。 以下是传递带有随机数的 WP 管理后台 AJAX 端点的示例: ```php // render.php wp_interactivity_state( 'myPlugin', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'myPlugin_nonce' ), ), ); ``` ```js // view.js const { state } = store( 'myPlugin', { actions: { *doSomething() { try { const formData = new FormData(); formData.append( 'action', 'do_something' ); formData.append( '_ajax_nonce', state.nonce ); const data = yield fetch( state.ajaxUrl, { method: 'POST', body: formData, } ).then( ( response ) => response.json() ); console.log( '服务器数据!', data ); } catch ( e ) { // 出现错误! } }, }, } ); ``` ### wp_interactivity_process_directives `wp_interactivity_process_directives` 在处理完指令后返回更新后的 HTML。 这是 Interactivity API 服务器端渲染部分的核心函数,且为公开函数,因此任何 HTML(无论是否为区块)都可以被处理。 以下代码: ```php wp_interactivity_state( 'myPlugin', array( 'greeting' => 'Hello, World!' ) ); $html_content = '
'; $processed_html = wp_interactivity_process_directives( $html_content ); echo $processed_html; ``` 将输出: ```html
Hello, World!
``` ### wp_interactivity_data_wp_context `wp_interactivity_data_wp_context` 返回上下文指令的字符串化 JSON。 此函数是在服务器端渲染标记中输出 `data-wp-context` 属性的推荐方式。 ```php $my_context = array( 'counter' => 0, 'isOpen' => true, ); ?>
>
``` 将输出: ```html
``` ### 私有存储 特定的存储命名空间可被标记为私有,从而阻止其他命名空间访问其内容。实现方式是在 `store()` 调用中添加 `lock` 选项,如下例所示。这样,后续对同一锁定命名空间执行 `store()` 时会抛出错误,意味着该命名空间仅能在首次 `store()` 调用返回引用的位置被访问。这对于希望隐藏部分插件存储、避免被扩展者访问的开发者特别有用。 ```js const { state } = store( 'myPlugin/private', { state: { messages: [ '私有信息' ] } }, { lock: true } ); // 以下调用会抛出错误! store( 'myPlugin/private', { /* 存储部分 */ } ); ``` 同时存在解锁私有存储的方法:可通过传递字符串(而非布尔值)作为 `lock` 参数。后续对同一命名空间的 `store()` 调用可使用该字符串解锁内容。只有知晓字符串锁的代码才能解锁受保护的存储命名空间。这对于在多个 JS 模块中定义的复杂存储非常实用。 ```js const { state } = store( 'myPlugin/private', { state: { messages: [ '私有信息' ] } }, { lock: PRIVATE_LOCK } ); // 以下调用可正常执行 store( 'myPlugin/private', { /* 存储部分 */ }, { lock: PRIVATE_LOCK } ); ``` ### 存储客户端方法 除存储函数外,还提供若干方法供开发者访问存储函数中的数据: - getContext() - getServerContext() - getServerState() - getElement() #### getContext() 获取由评估存储函数的元素继承的上下文。返回值取决于元素及调用 `getContext()` 函数所在的命名空间。该方法可接受可选命名空间参数,以获取特定交互区域的上下文。 ```js const context = getContext( '命名空间' ); ``` - `命名空间`(可选):与交互区域命名空间匹配的字符串。若未提供,则获取当前交互区域的上下文。 ```php // render.php
``` ```js // 存储模块 import { store, getContext } from '@wordpress/interactivity'; store( 'myPlugin', { actions: { log: () => { const context = getContext(); // 输出 "false" console.log( '上下文 => ', context.isOpen ); // 使用命名空间参数 const myPluginContext = getContext( 'myPlugin' ); // 输出 "false" console.log( 'myPlugin isOpen => ', myPluginContext.isOpen ); }, }, } ); ``` #### getServerContext() 此函数与 `getContext()` 类似,但存在两个关键差异: 1. 当调用 [`@wordpress/interactivity-router`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/) 中的 [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) 时,`getServerContext()` 返回的对象会同步更新。适用于需要根据通过 `actions.navigate()` 加载页面传来的**新**上下文更新区块上下文的情况。该新上下文会嵌入通过 `actions.navigate()` 加载页面的 HTML 中。 2. `getServerContext()` 返回的对象为只读。 服务器上下文不能直接在指令中使用,但可通过回调函数订阅其变更。 ```js const serverContext = getServerContext( '命名空间' ); ``` - `命名空间`(可选):与交互区域命名空间匹配的字符串。若未提供,则获取当前交互区域的服务器上下文。 使用示例: ```js store( 'myPlugin', { callbacks: { updateServerContext() { const context = getContext(); const serverContext = getServerContext(); // 用服务器传来的新值覆盖特定属性 context.overridableProp = serverContext.overridableProp; }, }, } ); ``` #### 副作用 自动响应状态变化。通常由 `data-wp-watch` 或 `data-wp-init` 指令触发。 #### 派生状态 返回经过计算的状态版本。可同时访问 `state` 和 `context`。 ```js // view.js const { state } = store( 'myPlugin', { state: { amount: 34, defaultCurrency: 'EUR', currencyExchange: { USD: 1.1, GBP: 0.85, }, get amountInUSD() { return state.currencyExchange[ 'USD' ] * state.amount; }, get amountInGBP() { return state.currencyExchange[ 'GBP' ] * state.amount; }, }, } ); ``` ### 在回调中访问数据 **`store`** 包含所有存储属性,如 `state`、`actions` 或 `callbacks`。这些属性通过 `store()` 调用返回,因此可以通过解构方式访问: ```js const { state, actions } = store( 'myPlugin', { // ... } ); ``` `store()` 函数可被多次调用,所有存储部分将被合并: ```js store( 'myPlugin', { state: { someValue: 1, }, } ); const { state } = store( 'myPlugin', { actions: { someAction() { state.someValue; // = 1 }, }, } ); ```
所有具有相同命名空间的 store() 调用都会返回相同的引用,即相同的 stateactions 等,包含所有传入存储部分的合并结果。
- 要在操作、派生状态或副作用中访问上下文,可使用 `getContext` 函数 - 要访问引用,可使用 `getElement` 函数 ```js const { state } = store( 'myPlugin', { state: { get someDerivedValue() { const context = getContext(); const { ref } = getElement(); // ... }, }, actions: { someAction() { const context = getContext(); const { ref } = getElement(); // ... }, }, callbacks: { someEffect() { const context = getContext(); const { ref } = getElement(); // ... }, }, } ); ``` 这种实现方式赋予指令灵活而强大的功能: - 操作和副作用可读取并修改状态及上下文 - 区块中的操作和状态可被其他区块访问 - 操作和副作用能执行常规 JavaScript 函数的所有操作,如访问 DOM 或发起 API 请求 - 副作用会自动响应状态变化 ### 设置存储 #### 客户端设置 开发者可在_每个区块的 `view.js` 文件_中定义状态和存储元素,引用操作、副作用或派生状态等功能。 用于在 JavaScript 中设置存储的 `store` 方法可从 `@wordpress/interactivity` 导入: ```js // store import { store, getContext } from '@wordpress/interactivity'; store( 'myPlugin', { actions: { toggle: () => { const context = getContext(); context.isOpen = ! context.isOpen; }, }, callbacks: { logIsOpen: () => { const { isOpen } = getContext(); // 每次 isOpen 变化时记录其值 console.log( `Is open: ${ isOpen }` ); }, }, } ); ``` #### 服务端设置 状态也可在服务端使用 `wp_interactivity_state()` 函数进行初始化。通常可在区块的 `render.php` 文件中实现(`render.php` 模板于 [WordPress 6.1](https://make.wordpress.org/core/2022/10/12/block-api-changes-in-wordpress-6-1/) 引入)。 通过 `wp_interactivity_state()` 在服务端定义的状态会与 view.js 文件中定义的存储合并。 `wp_interactivity_state` 函数接收两个参数:作为引用标识的命名空间`字符串`,以及包含值的[关联数组](https://www.php.net/manual/en/language.types.array.php)。 _从服务端初始化存储的示例(`state` = `{ someValue: 123 }`)_ ```php // render.php wp_interactivity_state( 'myPlugin', array ( 'someValue' => get_some_value() )); ``` 在服务端初始化状态还允许使用任何 WordPress API。例如,可使用核心翻译 API 翻译部分状态内容: ```php // render.php wp_interactivity_state( 'favoriteMovies', array( "1" => array( "id" => "123-abc", "movieName" => __("someMovieName", "textdomain") ), ) ); ``` ### `wp-text` 指令 该指令用于设置 HTML 元素的内部文本内容。 ```html
```
查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { actions: { toggleContextText: () => { const context = getContext(); context.text = context.text === '文本1' ? '文本2' : '文本1'; }, }, } ); ```
`wp-text` 指令会在以下时机执行: - 元素创建时 - 每当涉及获取指令最终值的 `state` 或 `context` 属性发生变化时(在回调函数或作为引用传递的表达式中) 返回值将用于改变元素的内部内容:`
数值
`。 ### `wp-on` 指令
若您的指令代码无需同步访问事件对象,建议改用性能更优的 wp-on-async。如需同步访问,可考虑实现 异步操作,在调用同步 API 后释放主线程控制权。
该指令用于在触发 DOM 事件(如 `click` 或 `keyup`)时执行代码。语法格式为 `data-wp-on--[事件名]`(例如 `data-wp-on--click` 或 `data-wp-on--keyup`)。 ```php ```
查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { actions: { logTime: ( event ) => { console.log( new Date() ); }, }, } ); ```
每当关联事件触发时,`wp-on` 指令便会执行。 作为引用传递的回调函数会接收[事件对象](https://developer.mozilla.org/en-US/docs/Web/API/Event)(`event`),该回调函数的返回值将被忽略。 ### `wp-on-async` 指令 这是 `wp-on` 指令的高性能版本。它会立即释放主线程控制权,避免造成长任务阻塞,让其他等待主线程的交互操作能更快执行。当不需要同步访问 `event` 对象(特别是 `event.preventDefault()`、`event.stopPropagation()` 和 `event.stopImmediatePropagation()` 方法)时,请使用此异步版本。 ### `wp-on-window` 指令
若您的指令代码无需同步访问事件对象,建议改用性能更优的 wp-on-async-window。如需同步访问,可考虑实现 异步操作,在调用同步 API 后释放主线程控制权。
该指令允许您绑定全局窗口事件(如 `resize`、`copy` 和 `focus`),并在事件触发时执行预定义的回调函数。 [支持的窗口事件列表](https://developer.mozilla.org/en-US/docs/Web/API/Window#events) 指令语法为 `data-wp-on-window--[窗口事件名]`(例如 `data-wp-on-window--resize` 或 `data-wp-on-window--languagechange`)。 ```php
```
查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { callbacks: { logWidth() { console.log( '窗口宽度: ', window.innerWidth ); }, }, } ); ```
作为引用传递的回调函数会接收[事件对象](https://developer.mozilla.org/en-US/docs/Web/API/Event)(`event`),该回调函数的返回值将被忽略。当元素从 DOM 中移除时,对应的事件监听器也会同步移除。 ### `wp-on-async-window` 指令 与 `wp-on-async` 类似,这是 `wp-on-window` 的优化版本,会立即释放主线程控制权以避免长任务阻塞。当不需要同步访问 `event` 对象(特别是 `event.preventDefault()`、`event.stopPropagation()` 和 `event.stopImmediatePropagation()` 方法)时,请使用此异步版本。此事件监听器还会以[被动模式](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#passive)进行注册。 #### getServerState() 获取交互区域的服务器状态。 此函数与 `getServerContext()` 用途相同,但返回的是**状态**而非**上下文**。 返回的对象为只读,包含通过 PHP 中 `wp_interactivity_state()` 定义的状态。当使用 [`@wordpress/interactivity-router`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/) 中的 [`actions.navigate()`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity-router/#actions) 时,`getServerState()` 返回的对象会更新以反映其属性的变化,而不会影响 `store()` 返回的状态。指令可以订阅这些变化以在需要时更新状态。 ```js const serverState = getServerState( 'namespace' ); ``` - `namespace`(可选):与交互区域命名空间匹配的字符串。如果未提供,则获取当前交互区域的服务器状态。 使用示例: ```js const { state } = store( 'myStore', { callbacks: { updateServerState() { const serverState = getServerState(); // 用服务器传来的新值覆盖某些属性。 state.overridableProp = serverState.overridableProp; }, }, } ); ``` #### getElement() 获取绑定或调用操作的元素表示。该表示为只读,包含对 DOM 元素的引用、其属性及本地响应式状态。 返回一个包含两个键的对象: ##### ref `ref` 是对 DOM 元素的引用,类型为 [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement)。相当于 Preact 或 React 中的 `useRef`,因此在 `ref` 尚未附加到实际 DOM 元素时(例如在水合或挂载期间)可能为 `null`。 ##### attributes `attributes` 包含一个 [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy),它添加了一个允许引用其他存储命名空间的 getter。欢迎在代码中查看该 getter。[链接](https://github.com/WordPress/gutenberg/blob/8cb23964d58f3ce5cf6ae1b6f967a4b8d4939a8e/packages/interactivity/src/store.ts#L70) 这些属性将包含该元素的指令。在按钮示例中: ```js // store import { store, getElement } from '@wordpress/interactivity'; store( 'myPlugin', { actions: { log: () => { const element = getElement(); // 输出属性 console.log( 'element attributes => ', element.attributes ); }, }, } ); ``` 代码将输出: ```json { "data-wp-on--click": 'actions.log', "children": ['Log'], "onclick": event => { evaluate(entry, event); } } ``` ### withScope() 操作在被调用时可能依赖于作用域,例如调用 `getContext()` 或 `getElement()` 时。 当交互 API 运行时执行回调时,作用域会自动设置。但是,如果从不由运行时执行的回调(如 `setInterval()` 回调)中调用操作,则需要确保作用域正确设置。在这些情况下,使用 `withScope()` 函数确保作用域正确设置。 例如,在没有包装器的情况下,`actions.nextImage` 会触发未定义错误: ```js store( 'mySliderPlugin', { callbacks: { initSlideShow: () => { setInterval( withScope( () => { actions.nextImage(); } ), 3_000 ); }, }, } ); ``` ### withSyncEvent() 需要同步访问 `event` 对象的操作必须使用 `withSyncEvent()` 函数来注解其处理程序回调。这是由于正在进行的努力,默认情况下将存储操作视为异步处理,除非它们需要同步事件访问。因此,从 Gutenberg 20.4 / WordPress 6.8 开始,所有需要同步事件访问的操作都必须使用 `withSyncEvent()` 函数。否则将触发弃用警告,并在未来版本中相应更改行为。 只有非常特定的事件方法和属性需要同步访问,因此建议仅在必要时使用 `withSyncEvent()`。以下事件方法和属性需要同步访问: * `event.currentTarget` * `event.preventDefault()` * `event.stopImmediatePropagation()` * `event.stopPropagation()` 以下示例展示了一个操作需要同步事件访问,而其他操作不需要的情况: ```js // store import { store, withSyncEvent } from '@wordpress/interactivity'; store( 'myPlugin', { actions: { // `event.preventDefault()` 需要同步事件访问。 preventNavigation: withSyncEvent( ( event ) => { event.preventDefault(); } ), // `event.target` 不需要同步事件访问。 logTarget: ( event ) => { console.log( 'event target => ', event.target ); }, // 完全不使用 `event` 不需要同步事件访问。 logSomething: () => { console.log( 'something' ); }, }, } ); ``` # API 参考
交互性 API 仅适用于 WordPress 6.5 及以上版本。
要通过交互性 API 为区块添加交互功能,开发者可以使用: - **指令:** 添加到标记中,为区块的 DOM 元素添加特定行为 - **存储:** 包含行为所需的逻辑和数据(状态、操作、副作用等) DOM 元素通过指令与存储在状态和上下文中的数据建立连接。如果状态或上下文中的数据发生变化,指令将响应这些变化,并相应地更新 DOM(参见[示意图](https://excalidraw.com/#json=T4meh6lltJh6TCX51NTIu,DmIhxYSGFTL_ywZFbsmuSw))。 ![状态与指令](https://make.wordpress.org/core/files/2024/02/interactivity-state-directives.png) ## 什么是指令? 指令是自定义属性,可添加到区块标记中,为其 DOM 元素添加行为。这可以在 `render.php` 文件(针对动态区块)或 `save.js` 文件(针对静态区块)中完成。 交互性 API 指令使用 `data-` 前缀。以下是一个在 HTML 标记中使用指令的示例: ```html

此元素现在可见!

``` 指令还可以使用 [HTML 标签处理器](https://make.wordpress.org/core/2023/03/07/introducing-the-html-api-in-wordpress-6-2)动态注入。 通过指令,可以直接管理交互,例如副作用、状态、事件处理程序、属性或内容。 ## 指令列表 ### `wp-interactive` `wp-interactive` 指令通过交互性 API(指令和存储)为 DOM 元素及其子元素“激活”交互功能。该指令包含一个命名空间,用于引用特定的存储,可以设置为 `string` 或 `object`。 ```html

我现在具有交互性, 并且可以使用指令!

我也具有交互性, 并且我也可以使用指令!

我现在具有交互性, 并且可以使用指令!

我也具有交互性, 并且我也可以使用指令!

```
使用 data-wp-interactive 是交互性 API“引擎”工作的必要条件。在以下示例中,为了简化,未添加 data-wp-interactive。此外,data-wp-interactive 指令将在未来自动注入。
### `wp-context` 它提供了一个**局部**状态,可供特定的 HTML 节点及其子节点使用。 `wp-context` 指令接受一个字符串化的 JSON 作为值。 ```php // render.php
```
查看与上述指令一起使用的存储 ```js store( 'myPlugin', { actions: { logId: () => { const { post } = getContext(); console.log( post.id ); }, }, } ); ```
可以在不同层级定义不同的上下文,更深层级的上下文会将其自身的上下文与任何父级上下文合并: ```html
``` ### `wp-on-document`
若您的指令代码无需同步访问事件对象,建议改用性能更佳的 wp-on-async-document。如需同步访问,可考虑实现一个异步操作,在调用同步 API 后主动让出主线程。
该指令允许您绑定全局文档事件(如 `scroll`、`mousemove` 和 `keydown`),并在事件触发时执行预定义的回调函数。 [支持的文档事件列表](https://developer.mozilla.org/en-US/docs/Web/API/Document#events) 指令语法为 `data-wp-on-document--[文档事件名]`(例如 `data-wp-on-document--keydown` 或 `data-wp-on-document--selectionchange`)。 ```php
```
查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { callbacks: { logKeydown( event ) { console.log( '按键按下: ', event.key ); }, }, } ); ```
传入的回调函数会接收[事件对象](https://developer.mozilla.org/en-US/docs/Web/API/Event)(`event`),其返回值将被忽略。当元素从 DOM 中移除时,对应的事件监听器也会同步移除。 ### `wp-on-async-document` 与 `wp-on-async` 类似,这是 `wp-on-document` 的优化版本,会立即让出主线程以避免造成长任务。当不需要同步访问 `event` 对象(特别是 `event.preventDefault()`、`event.stopPropagation()` 和 `event.stopImmediatePropagation()` 方法)时,请使用此异步版本。此事件监听器还会被添加为[被动模式](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#passive)。 ### `wp-watch` 该指令会在**节点创建时执行回调,并在状态或上下文变更时重新执行**。 您可以通过 `data-wp-watch--[唯一标识]` 语法为同一 DOM 元素附加多个副作用回调。 `唯一标识` 无需全局唯一,只需在该 DOM 元素的 `wp-watch` 指令中保持唯一性即可。 ```html

计数器:

```
查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { actions: { increaseCounter: () => { const context = getContext(); context.counter++; }, decreaseCounter: () => { const context = getContext(); context.counter--; }, }, callbacks: { logCounter: () => { const { counter } = getContext(); console.log( '计数器值:' + counter + ' 记录时间:' + new Date() ); }, }, } ); ```
`wp-watch` 指令会在以下时机执行: - 元素创建时 - 回调函数内部使用的 `state` 或 `context` 属性发生变更时 `wp-watch` 指令可返回一个函数。若返回函数,该函数将作为清理逻辑使用:在回调再次执行前运行,并在元素从 DOM 移除时再次执行。 典型使用场景包括: - 日志记录 - 修改页面标题 - 通过 `.focus()` 设置元素焦点 - 满足特定条件时更新状态或上下文 ### `wp-init` 该指令**仅在节点创建时执行一次回调**。 您可以通过 `data-wp-init--[唯一标识]` 语法为同一 DOM 元素附加多个 `wp-init` 指令。 `唯一标识` 无需全局唯一,只需在该 DOM 元素的 `wp-init` 指令中保持唯一性即可。 ```html

您好!

``` 以下示例展示了同一 DOM 元素上多个 `wp-init` 指令的用法: ```html
```
查看与上述指令配合使用的存储模块 ```js import { store, getElement } from '@wordpress/interactivity'; store( "myPlugin", { callbacks: { logTimeInit: () => console.log( `初始化时间:` + new Date() ), focusFirstElement: () => { const { ref } = getElement(); ref.querySelector( 'input:first-child' ).focus(), }, }, } ); ```
若 `wp-init` 指令返回函数,该函数会在元素从 DOM 移除时执行。 ### `wp-bind` 指令 该指令允许根据布尔值或字符串值为元素设置 HTML 属性。其语法格式为 `data-wp-bind--attribute`。 ```html
  • 标题
  • ```
    查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { actions: { toggleMenu: () => { const context = getContext(); context.isMenuOpen = ! context.isMenuOpen; }, }, } ); ```
    `wp-bind` 指令在以下情况执行: - 元素创建时 - 每当影响指令最终值的 `state` 或 `context` 属性发生变化时(在回调函数或传递的引用表达式中) 当 `wp-bind` 指令引用回调函数获取最终值时: - 只要该回调函数内使用的 `state` 或 `context` 属性发生变化,`wp-bind` 指令就会执行 - 回调函数的返回值将用于修改对应属性的值 `wp-bind` 根据值的不同会对 DOM 元素进行不同操作: - 值为 `true` 时添加属性:`
    ` - 值为 `false` 时移除属性:`
    ` - 值为字符串时添加属性并赋值:`
    ` - 属性名以 `aria-` 或 `data-` 开头且值为布尔值时,会将布尔值转为字符串添加到 DOM:`
    ` ### `wp-class` 指令 该指令根据布尔值为 HTML 元素添加或移除类名。其语法格式为 `data-wp-class--classname`。 ```html
  • 选项 1
  • 选项 2
  • ```
    查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { actions: { toggleSelection: () => { const context = getContext(); context.isSelected = ! context.isSelected; }, }, } ); ```
    `wp-class` 指令在以下情况执行: - 元素创建时 - 每当影响指令最终值的 `state` 或 `context` 属性发生变化时(在回调函数或传递的引用表达式中) 指令接收的布尔值用于切换 `class` 属性中的关联类名(值为 `true` 时添加,值为 `false` 时移除)。 需要注意:使用 `wp-class` 指令时,推荐使用短横线命名法而非驼峰命名法。因为 HTML 属性不区分大小写,`data-wp-class--isDark`、`data-wp-class--isdark` 和 `DATA-WP-CLASS--ISDARK` 在 HTML 中会被视为相同属性。 因此,建议使用 `is-dark` 替代 `isDark`,使用 `data-wp-class--is-dark` 替代 `data-wp-class--isDark`: ```html
    ``` ```css /* 推荐用法 */ .is-dark { /* ... */ } /* 不推荐用法 */ .isDark { /* ... */ } ``` ### `wp-style` 指令 该指令根据值为 HTML 元素添加或移除内联样式。其语法格式为 `data-wp-style--css-property`。 ```html

    Hello World!

    ```
    查看与上述指令配合使用的存储模块 ```js store( 'myPlugin', { actions: { toggleContextColor: () => { const context = getContext(); context.color = context.color === 'red' ? 'blue' : 'red'; }, }, } ); ```
    `wp-style` 指令在以下情况执行: - 元素创建时 - 每当影响指令最终值的 `state` 或 `context` 属性发生变化时(在回调函数或传递的引用表达式中) 指令接收的值用于添加或移除包含对应 CSS 属性的样式属性: - 值为 `false` 时移除样式属性:`
    ` - 值为字符串时添加样式属性并赋值:`
    ` ### `wp-run` 指令 该指令会在**节点渲染执行期间**运行传入的回调函数。 您可以在传入的回调中使用并组合诸如 `useState`、`useWatch` 或 `useEffect` 之类的钩子,创建自己的逻辑,相比之前的指令提供了更大的灵活性。 您可以通过 `data-wp-run--[唯一标识符]` 语法在同一个 DOM 元素上附加多个 `wp-run` 指令。 `唯一标识符` 不需要全局唯一,只需与该 DOM 元素上其他 `wp-run` 指令的唯一标识符不同即可。 ```html

    你好!

    ```
    查看与上述指令配合使用的存储 ```js import { getElement, store, useState, useEffect, } from '@wordpress/interactivity'; // 与 `data-wp-init` 和 `data-wp-watch` 不同,您可以在 `data-wp-run` 回调中使用任何钩子。 const useInView = () => { const [ inView, setInView ] = useState( false ); useEffect( () => { const { ref } = getElement(); const observer = new IntersectionObserver( ( [ entry ] ) => { setInView( entry.isIntersecting ); } ); observer.observe( ref ); return () => ref && observer.unobserve( ref ); }, [] ); return inView; }; store( 'myPlugin', { callbacks: { logInView: () => { const isInView = useInView(); useEffect( () => { if ( isInView ) { console.log( '在视口内' ); } else { console.log( '在视口外' ); } } ); }, }, } ); ```
    需要注意的是,与 (P)React 组件类似,在首次渲染期间,`getElement()` 返回的 `ref` 为 `null`。要正确访问 DOM 元素引用,通常需要使用类似效果的钩子,如 `useEffect`、`useInit` 或 `useWatch`。这确保了 `getElement()` 在组件挂载后运行,并且 `ref` 可用。 ### `wp-key` 指令 `wp-key` 指令为元素分配一个唯一键,以帮助交互式 API 在遍历元素数组时识别它。如果您的数组元素可能移动(例如,由于排序)、插入或删除,这一点就变得很重要。选择恰当的键值有助于交互式 API 推断数组中具体发生了哪些变化,从而使其能够正确更新 DOM。 键应是一个字符串,用于在兄弟元素中唯一标识该元素。通常,它用于重复元素,如列表项。例如: ```html
    • 项目 1
    • 项目 2
    ``` 但它也可以用于其他元素: ```html ``` 当列表重新渲染时,交互式 API 将通过元素的键进行匹配,以确定是否添加/删除/重新排序了项目。没有键的元素可能会不必要地重新创建。 ### `wp-each` 指令 `wp-each` 指令用于渲染元素列表。该指令可以在 `