初探 WordPress 交互性 API
交互性 API 在 WordPress 6.4 中作为私有 API 引入,仅供核心区块使用。随着 WordPress 6.5 的发布,该 API 已公开,开发者现在可以在自定义项目中使用它。
过去,Gutenberg 开发主要专注于增强区块的后端功能,这主要影响内容创作者。而交互性 API 则专注于前端。
通常,用户通过点击或滚动页面与网站互动。交互性 API 允许你为区块添加响应式行为。这些行为可以包括简单的效果,例如点击显示/隐藏元素或滚动时动画元素,以及更高级的功能,如无需重新加载页面的导航或即时搜索。
一个使用交互性 API 构建功能的实际例子是 WordPress 6.4 中添加的核心图片区块的灯箱选项。
传统上,这类功能长期以来都是用 jQuery 编码的,即使在今天,许多主题和插件仍然依赖它。交互性 API 旨在减少 WordPress 项目中 jQuery 的使用,并成为编码交互元素的新标准。
交互性 API 概述
交互性 API 与其他 JS 框架有许多相似之处,特别是 Alpine.js,这使得任何已经熟悉现代 JavaScript 生态系统的人都能轻松上手。
它通过指令扩展了标准 HTML,这些指令是特殊的数据属性,可以监听和修改任何 DOM 元素的行为。使用指令,你可以操作 DOM、应用 CSS 样式、处理用户输入等等。
需要强调的是,区块创建的工作流程没有改变。要为区块添加交互性,你需要使用交互性 API 的新功能来扩展它。你仍然可以使用 @wordpress/create-block 脚手架工具,并像往常一样开发区块的编辑器部分。
要使用交互性 API 为区块添加交互性,你需要:
- 添加指令 作为数据属性到 HTML 标记中,为区块添加特定行为。通常你会在区块目录的
render.php文件中添加它们(WordPress 6.5 仅支持动态区块)。所有公开可用的指令列表可以在 交互性 API 参考 中找到。 - 创建一个 Store,包含交互性所需的逻辑(状态、动作或回调)。通常,它被添加到区块目录的
view.js文件中。在 Store 中,动作 可以定义为响应用户交互(如点击)而运行的函数。动作更新全局状态或本地上下文,进而更新连接到其中任何一个的 HTML 元素。除了动作,你还可以定义作为副作用运行的回调。回调也是函数,但不是由用户交互直接调用,而是由状态变化触发。你可以在 文档 中阅读更多关于 Store 的信息。
本文的下一部分将演示如何为一个慈善机构编码一个区块,允许用户计算他们计划捐赠的金额可以种植多少棵树。到最后,你应该对如何使用交互性 API 有一个很好的掌握。
前提条件
本教程假设你熟悉构建自定义区块的基础知识,例如开发环境、文件结构、block.json 元数据、区块的静态与动态渲染等。还假设你已经至少构建过一个基本区块。如果不是这种情况,建议先阅读 构建你的第一个区块 教程。
创建一个基本的切换区块
第一步是使用交互性 API 模板 @wordpress/create-block-interactive-template 搭建初始区块结构。最好在本地 WordPress 安装的 /plugins 目录中运行它。
npx @wordpress/create-block@latest donation-calculator --template @wordpress/create-block-interactive-template
接下来,使用命令 cd donation-calculator 导航到区块目录,并使用 npm start 开始开发。
脚手架工具创建了一个基本的交互式切换区块,在 WordPress 管理面板中激活插件后,该区块应该可以在编辑器中使用。
现在让我们检查生成的代码,以了解是什么让这个区块具有交互性。
打开 /src 文件夹中的 block.json 文件。在 supports 部分,你应该看到 interactivity 被设置为 true。这一行对于在区块中启用交互性 API 是必需的。同时,确保定义了 viewScriptModule 属性,并且指向 view.js 文件的路径是正确的。
"supports": {
"interactivity": true
},
"viewScriptModule": "file:./view.js"
wp-interactive 指令
现在打开包含区块前端标记的 render.php 文件。
<?php
$unique_id = wp_unique_id( 'p-' );
?>
<div
<?php echo get_block_wrapper_attributes(); ?>
data-wp-interactive="create-block"
<?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false ) ); ?>
data-wp-watch="callbacks.logIsOpen"
>
<button
data-wp-on--click="actions.toggle"
data-wp-bind--aria-expanded="context.isOpen"
aria-controls="<?php echo esc_attr( $unique_id ); ?>"
>
<?php esc_html_e( 'Toggle', 'donation-calculator' ); ?>
</button>
<p
id="<?php echo esc_attr( $unique_id ); ?>"
data-wp-bind--hidden="!context.isOpen"
>
<?php
esc_html_e( 'Donation Calculator - hello from an interactive block!', 'donation-calculator' );
?>
</p>
</div>
一些数据属性已被添加到 HTML 标记中。这些就是本文前面提到的指令。它们都遵循 data-wp-directiveName 语法。
wp-interactive 指令 通过交互性 API 为包装 <div> 及其子元素激活交互性。它包含一个命名空间 create-block,用于引用 view.js 文件中定义的 Store。
import { store, getContext } from '@wordpress/interactivity';
store( 'create-block', {
actions: {
toggle: () => {
const context = getContext();
context.isOpen = ! context.isOpen;
},
},
callbacks: {
logIsOpen: () => {
const { isOpen } = getContext();
// Log the value of `isOpen` each time it changes.
console.log( `Is open: ${ isOpen }` );
},
},
} );
wp-interactive 指令中的命名空间应与 store 函数的第一个参数匹配。你可以将 create-block 命名空间更改为与插件名称匹配的命名空间——在本例中为 donation-calculator。此更改需要在两个文件中更新——render.php 和 view.js。
wp-context 指令
此区块中的交互非常常见——当用户点击按钮时显示或隐藏段落。要存储有关段落可见性的信息,你需要一个上下文。使用交互性 API,你可以使用 wp_interactivity_data_wp_context() 函数,可以将其添加到包装 <div> 中。上下文是局部的,对 <div> 及其所有子元素可用,但对其他区块不可用。
wp_interactivity_data_wp_context() 函数返回上下文指令的字符串化 JSON。在此区块中,wp-context 在 isOpen 键下存储有关段落可见性的信息,初始值为 false。此值稍后将用于根据用户交互有条件地从段落中添加或删除 hidden 属性。
<div
<?php echo get_block_wrapper_attributes(); ?>
data-wp-interactive="donation-calculator"
<?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false ) ); ?>
data-wp-watch="callbacks.logIsOpen"
>
wp-on 指令
接下来,需要向按钮添加事件监听器以处理点击。交互性 API 提供了 wp-on 指令 来监听 DOM 事件。
该指令遵循语法 data-wp-on--[event]。
在此示例中,data-wp-on--click 指令被添加到按钮。在 Store 中声明为动作的函数名称 toggle 作为值传递。
<button
data-wp-on--click="actions.toggle"
data-wp-bind--aria-expanded="context.isOpen"
aria-controls="<?php echo esc_attr( $unique_id ); ?>"
>
<?php esc_html_e( 'Toggle', 'donation-calculator' ); ?>
</button>
接下来,需要创建逻辑——当用户点击按钮时应该发生什么。由于交互性 API 遵循声明式方法,用户交互触发的事件不会直接修改 HTML 元素。相反,它应该更新状态或上下文,交互性 API 将负责更新连接到其中任何一个的元素。
在此区块中,当用户点击按钮时,它会触发一个动作,将 isOpen 上下文设置为相反的值(例如,从 false 到 true)。然后交互性 API 会自动显示或隐藏 <p> 元素。
让我们打开 view.js 文件,检查在 Store 的 actions 属性中定义的 toggle() 函数。
store( 'donation-calculator', {
actions: {
toggle: () => {
const context = getContext();
context.isOpen = ! context.isOpen;
},
},
});
toggle() 函数首先使用 getContext() 检索当前上下文属性,然后将 isOpen 属性设置为相反的值。这就是该函数所做的全部。
要验证逻辑是否按预期工作,你可以在 toggle() 函数的最后一行下添加 console.log( context.isOpen );。现在,当你点击按钮时,你应该在控制台中看到该值随着每次点击而变化。
交互性 API 还为 window 和 document 事件监听器提供了指令。更多详细信息,你可以参考 文档。
wp-bind 指令
要使切换区块工作,你需要将要显示或隐藏的段落连接到 isOpen 上下文。你使用 wp-bind 指令,它允许根据布尔值或字符串值在元素上设置 HTML 属性。
该指令遵循语法 data-wp-bind--[attribute]。
在此示例中,仅当 isOpen 上下文设置为 false 时,才应将 hidden 属性添加到段落。因此,需要将 data-wp-bind--hidden 属性添加到 <p> 元素,并为其分配 context.isOpen 的相反值。
<p
id="<?php echo esc_attr( $unique_id ); ?>"
data-wp-bind--hidden="!context.isOpen"
>
<?php
esc_html_e( 'Donation Calculator - hello from an interactive block!', 'donation-calculator' );
?>
</p>
当 isOpen 设置为 false 时,hidden 属性将被添加到 <p>,因此它将不再可见。当它设置为 true 时,hidden 属性将被移除,段落将再次可见。
wp-class 指令
或者,你可以通过添加一个 CSS 属性 display 设置为 none 的类 .hidden 来隐藏段落。交互性 API 包含一个 wp-class 指令,它根据布尔值有条件地添加或删除类。
该指令遵循语法 data-wp-class--[classname]。
让我们继续将段落上的 data-wp-bind--hidden 属性替换为 data-wp-class--hidden,并保持值不变。你还需要将 .hidden {display: none} 代码添加到区块目录中的 style.scss 文件。
<p
id="<?php echo esc_attr( $unique_id ); ?>"
data-wp-class--hidden="!context.isOpen"
>
<?php
esc_html_e( 'Donation Calculator - hello from an interactive block!', 'donation-calculator' );
?>
</p>
当 isOpen 设置为 false 时,class="hidden" 属性将被添加到 <p>,使其不再可见。当它设置为 true 时,该类将被移除。
wp-style 指令
隐藏段落的另一种方法是为段落添加内联样式,值为 display:none。交互性 API 包含一个 wp-style 指令,用于添加或删除元素的内联样式。
该指令遵循语法 data-wp-style--[css-property]。
要使用 display CSS 属性,你需要将 data-wp-style--display 指令添加到 <p> 元素,并将其设置为 none 或 block。你不能直接使用 context.isOpen 作为值,因为它返回 true 或 false,但你可以将其用作派生状态的基础,该状态将从其计算得出。
交互性 API Store 有另一个名为 state 的属性,你可以在其中使用 getter 函数定义派生状态或上下文。让我们创建一个 display() getter。如果 context.isOpen 为 false,它将返回 none;当为 true 时返回 block。
store( 'donation-calculator', {
state: {
get display() {
const context = getContext();
return context.isOpen ? 'block' : 'none';
}
},
actions: {
toggle: () => {
const context = getContext();
context.isOpen = ! context.isOpen;
}
},
});
然后,你可以在 data-wp-style--display 指令中使用 display() getter,将其视为任何其他状态属性,将其称为 state.display。让我们将其添加到段落中。
<p
id="<?php echo esc_attr( $unique_id ); ?>"
data-wp-style--display="state.display"
>
<?php
esc_html_e( 'Donation Calculator - hello from an interactive block!', 'donation-calculator' );
?>
</p>
创建捐赠计算器
让我们修改区块,为慈善组织创建一个捐赠计算器。它将有一个表单,网站访问者可以在其中输入他们愿意捐赠的金额。然后计算器将计算并显示该组织可以用指定捐赠种植的树木数量。该区块将允许网站管理员设置种植一棵树的价格,该价格将用于计算。
你可以采取以下几个步骤:
- 定义一个存储价格的属性(
block.json) - 添加一个控件,编辑器可以在其中设置种植一棵树的价格,并包含表单的视觉预览(
edit.js) - 对区块的 HTML 标记进行一些更改,例如添加表单、添加交互性 API 指令等。(
render.php) - 定义处理计算的动作和 getter 函数(
view.js) - 为区块添加样式(
style.scss和editor.scss)
在编辑器中添加价格控制
首先,定义一个属性,用来存储编辑页面的人设置的树种价格。将该属性添加到 的现有元素中。属性会有一个类型 和 默认值,计算器会用这个值,以防编辑器不设定价格。priceattributesblock.jsonpricenumber
block.json"attributes": {
"price": {
"type": "number",
"default": 15
}
},
接下来,创建该块的编辑器视图。把这段代码加到edit.js文件里。
edit.jsimport { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { __experimentalNumberControl as NumberControl, PanelBody
} from '@wordpress/components';
export default function Edit( { attributes, setAttributes } ) {
const { price } = attributes;
const exampleDonationAmount = 1000;
const trees = Math.floor( exampleDonationAmount / price );
return (
<div { ...useBlockProps() }>
<InspectorControls>
<PanelBody title={ __( 'Calculator settings' ) }>
<NumberControl
label={ __( 'Set the price for one tree' ) }
help={ __( 'The value will be used for calculations.' ) }
value={ price }
min={ 1 }
onChange={
( value ) =>
setAttributes( {
price: Number( value )
} )
}
/>
</PanelBody>
</InspectorControls>
<form className="calculator">
<label for="contribution-value" className="calculator-label">{ __( 'Check the impact of your donation:' ) }</label>
<div class="calculator-input">$
<input disabled value={ exampleDonationAmount } className="calculator-input-form" type="number" id="contribution-value"/>
</div>
<output className="calculator-output">
{[
__( 'Your ' ),
<span>${ exampleDonationAmount }</span>,
__( ' donation will enable us to plant ' ),
<span>{ trees }</span>,
__( ' trees.' )
]}
</output>
</form>
</div>
);
}
你在 WordPress 6.5 中无法在模块后台添加 Interactivity API。它将作为表单预览,包含一些预定义的数据和价格控制。计算器只能在前端为网站访客工作。
为区块添加样式
你还需要在块里添加一些样式。你可以复制以下CSS,添加到块目录里的文件中。style.scss
style.scss.wp-block-create-block-donation-calculator {
box-sizing: border-box;
background-color: #f2fcf6;
color: #023a51;
border: 3px solid #023a51;
border-radius: 1.5rem;
text-align: center;
overflow: hidden;
.calculator {
padding: 3rem 2rem;
&-input {
margin: 1.25rem auto;
font-size: 1.75rem;
color: #023a51;
display: flex;
justify-content: center;
align-items: center;
&-form{
padding: 0.5rem 1rem;
margin-left: 0.5rem;
border: 2px solid #023a51;
border-radius: 1rem;
background-color: #fff;
font-size: 1.5rem;
color: #023a51;
max-width: 130px;
}
}
&-output {
display: none;
&.show {
display: block;
}
span {
color: #f2fcf6;
background: #0cab49;
font-weight: bold;
border-radius: 5px;
padding: 0.25rem 0.5rem;
}
}
}
}
在后端添加样式(在editor.scss 中),使信息段落在编辑器中始终可见。
editor.scss.wp-block-create-block-donation-calculator {
.calculator-output {
display: block;
}
}
编辑者对该区块的视图:

创建块的前端视图
编辑器中的价格控制允许用户设置植树价格。该值存储在属性中,属性可以通过数组在文件中的键访问,按键定义。pricerender.php$attributesblock.json
你可以通过 访问价格,该 存储用户输入的值或默认值。$attributes['price']15
价格会传递到上下文,以便交互性API使用。你可以使用wp_interactivity_data_wp_context()函数设置初始上下文,将存储用户输入字段中的值。pricecontribution
把文件里的所有东西都删掉,然后为计算表单添加新的标记。render.php
render.php<?php
$context = array(
'price' => (int)$attributes['price'],
'contribution' => 0
);
?>
<div
<?php echo get_block_wrapper_attributes(); ?>
data-wp-interactive="donation-calculator"
<?php echo wp_interactivity_data_wp_context( $context ); ?>
>
<form aria-label="<?php esc_attr_e( 'Calculate the impact of your donation.' ); ?>" class="calculator">
<label for="contribution-value" class="calculator-label"><?php esc_html_e( 'Check the impact of your donation:' ); ?></label>
<div class="calculator-input">$
<input
data-wp-on--input="actions.calculate"
placeholder="0"
type="number"
id="contribution-value"
class="calculator-input-form"
>
</div>
</form>
</div>
该块的前端现在应该是这样的:

注意输入元素中添加的指令。data-wp-on--input="actions.calculate"
一旦用户开始输入,将调用 的 actions 属性下定义的函数。表单中输入的数字作为事件对象(e)传递给函数,并作为属性访问。该函数会保存calculate()storee.target.valuecalculate()context.contribution属性中的值。
简短的信息框应该会出现在表格下方,说明用户愿意捐赠的金额下可以种植多少棵树。这两个数值可以由 推导出。第一个(树木数量)通过将捐赠金额除以价格计算,第二个(带$符号的价值)则通过将数字转换为字符串生成。context.contribution
最后,表单输出只有在用户输入大于0的数字时才会显示。样式的值由context.contribution推导。
在状态属性下,我们添加以下获取函数:
donation(): 返回带有 $ 符号的格式化值,作为字符串trees():返回将价值除以价格(向下取整)的结果show():如果用户输入的值大于0,则返回,否则truefalse
这个逻辑需要在文件中添加。view.js
view.jsimport { store, getContext } from '@wordpress/interactivity';
store( 'donation-calculator', {
state: {
get donation() {
const context = getContext();
return `$${context.contribution}`;
},
get trees() {
const context = getContext();
return Math.floor( context.contribution / context.price );
},
get show() {
const context = getContext();
return context.contribution > 0;
}
},
actions: {
calculate: ( e ) => {
const context = getContext();
context.contribution = Number( e.target.value );
}
}
} );
WP-文本指令
剩下的任务是在表单下方显示贡献信息。
交互性 API 包含一个用于设置内部 HTML 的指令。你需要把它添加到元素内部的标签里。wp-text<span><output>
然后将指令连接到对应的状态获取器,将第一个状态获取器与 。这会显示用户输入的值,并带有$符号的表单。第二个>显示可种植的树木数量。wp-text<span><output>state.donation<spanstate.trees
指令管理这些区间内HTML的设置,每当用户在表单字段输入数字时,都会重新渲染。wp-text
完成此练习时,你需要将指令添加到元素中。下面你会看到完整的代码。data-wp-class--show="state.show"outputrender.php
render.php<?php
$context = array(
'price' => (int)$attributes['price'],
'contribution' => 0
);
?>
<div
data-wp-interactive="donation-calculator"
<?php echo wp_interactivity_data_wp_context( $context ); ?>
<?php echo get_block_wrapper_attributes(); ?>
>
<form aria-label="<?php esc_attr_e( 'Calculate the impact of your donation.' ); ?>" class="calculator">
<label for="contribution-value" class="calculator-label"><?php esc_html_e( 'Check the impact of your donation:' ); ?></label>
<div class="calculator-input">$
<input
data-wp-on--input="actions.calculate"
placeholder="0"
type="number"
id="contribution-value"
class="calculator-input-form"
>
</div>
<output
class="calculator-output"
data-wp-class--show="state.show"
>
<?php
echo sprintf(
esc_html__( 'Your %s donation will enable us to plant %s trees.' ),
'<span data-wp-text="state.donation"></span>',
'<span data-wp-text="state.trees"></span>'
);?>
</output>
</form>
</div>
了解更多关于交互性 API 的资源
- API 参考——官方文档
- WP 简报讨论交互性 API
- 开发说明:6.5版本的交互性API
- 开发者小时:探索 WordPress 6.5 中的互动性 API
- 开发者小时:利用交互性API构建自定义模块
交互性 API 目前正在开发中,更多功能仍在规划中。更多细节可以参考GitHub相关问题。