
在本部落格之前的文章中,我們從多個角度探討了 WordPress 區塊開發。我們研究了靜態區塊和動態區塊的開發,並擴充套件了核心區塊的功能。然而,我們目前採用的方法本質上只能建立無法即時響應使用者互動的標準區塊。簡而言之,這些區塊是不互動式的。
在本文中,我們將探索一種全新的區塊開發方法,藉助強大的全新 WordPress API——WordPress Interactivity API,我們將能夠建立互動式區塊。該 API 在 WordPress 6.5 中引入,使您能夠建立可即時響應使用者互動的區塊,從而打造豐富的使用者體驗,讓您的網站更具吸引力、動態性和互動性。
內容豐富,但在開始之前,讓我們先來看看一些基本要求!
使用互動API之前需要準備什麼
由於互動 API 基於 React,您至少需要具備伺服器端 JavaScript 和 React 的基礎知識,以及 npm 和 npx 等構建工具的使用經驗。此外,您還需要深入瞭解 WordPress 開發和 Gutenberg 區塊編輯器。
掌握必要的技能後,您需要一個本地開發環境,以便快速輕鬆地啟動 WordPress 網站。我們適用類似 DevKinsta 的工具,這是一款專為 WordPress 設計的本地開發套件。使用 DevKinsta,您只需點選幾下即可設定一個新的本地 WordPress 網站,並進行詳細的自定義。
在 DevKinsta 中建立新的 WordPress 專案時,您可以設定以下選項:
- 頂級域名:預設 .local
- PHP 版本
- 資料庫名稱
- 啟用 HTTPS
- WordPress 詳細資訊
- WordPress 自動更新
- 多站點
此外,您還可以從備份匯入現有的 MyKinsta 網站。

在 DevKinsta 中配置本地網站
什麼是互動API?
互動 API 是 WordPress 原生 API,它允許您為 Gutenberg 區塊新增互動功能,進而為 WordPress 網站上的文章和頁面新增互動功能。它是一個輕量級、現代化的解決方案,採用宣告式方法來管理使用者互動。
從頭開始建立互動式區塊需要高階 PHP 和伺服器端 JavaScript 開發技能。但是,您無需在每個新專案中都重複造輪子,因為 WordPress 提供了一個用於建立互動式區塊的模板:
npx @wordpress/create-block --template @wordpress/create-block-interactive-template
此模板包含搭建互動式模組所需的一切,包括兩個可供您參考的示例:一個用於切換當前主題的按鈕和一個用於展開/摺疊段落的按鈕。
要開始使用,請開啟您常用的命令列工具,導航到本地 WordPress 安裝目錄下的 Plugins 資料夾,然後輸入以下命令:
npx @wordpress/create-block your-interactive-block --template @wordpress/create-block-interactive-template
請稍等片刻,待安裝完成後,使用您常用的程式碼編輯器開啟專案資料夾。我們推薦使用 Visual Studio Code,但您也可以使用任何您用起來最順手的編輯器。

此互動式區塊專案由 @wordpress/create-block-interactive-template 提供。
在命令列中,導航到新外掛的資料夾,並使用以下命令啟動開發伺服器:
npm start
從現在開始,您對模組所做的任何更改都將在 WordPress 中即時顯示。
接下來,在 WordPress 管理後臺,導航至“Plugins”頁面,並啟用您剛剛建立的“Interactivity API”外掛。建立一個新文章或頁面,然後在模組插入器中搜尋您的互動式區塊,並將其新增到您的內容中。儲存文章並在前端預覽。您將看到一個包含兩個按鈕的黃色模組。第一個按鈕用於更改模組的背景顏色,第二個按鈕用於顯示或隱藏段落內容。

@wordpress/create-block-interactive-template 提供的互動式區塊示例。
現在您已經有了可以參考的外掛,本文涵蓋的主題也已包含在內,我們可以繼續深入探索互動式區塊。
互動式區塊的結構
互動式區塊的結構與傳統區塊相同。您仍然需要 package.json、block.json、edit.js 和 style.scss 檔案。此外,您還需要 render.php 檔案用於伺服器端渲染,以及 view.js 檔案用於處理前端互動。
讓我們透過分析初始專案的各個檔案來了解互動式區塊的具體組成部分。
package.json
package.json 檔案用於 Node 專案中,用於標識您的專案、管理指令碼以及在開發過程中管理和安裝依賴項。
以下是 create-block-interactive-template 提供的互動式區塊的 package.json 檔案:
{
"name": "your-interactive-block",
"version": "0.1.0",
"description": "An interactive block with the Interactivity API.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build --experimental-modules",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"packages-update": "wp-scripts packages-update",
"plugin-zip": "wp-scripts plugin-zip",
"start": "wp-scripts start --experimental-modules"
},
"dependencies": {
"@wordpress/interactivity": "latest"
},
"files": [
"[^.]*"
],
"devDependencies": {
"@wordpress/scripts": "^30.24.0"
}
}
這裡 scripts 和 dependencies 部分尤為重要。
build:將原始碼編譯成用於生產環境的 JavaScript。--experimental-modules選項啟用對 WordPress 指令碼模組的支援。start:啟動開發伺服器。請注意,這裡再次指定了--experimental-modules選項。dependencies:包含執行時依賴項以及最新的 Interactivity API 包。
block.json
block.json 檔案是 Gutenberg 區塊的清單檔案。它指定要載入的後設資料、媒體、指令碼和樣式。預設情況下,create-block-interactive-template 會生成以下 block.json 檔案:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "create-block/your-interactive-block",
"version": "0.1.0",
"title": "Your Interactive Block",
"category": "widgets",
"icon": "media-interactive",
"description": "An interactive block with the Interactivity API.",
"example": {},
"supports": {
"interactivity": true
},
"textdomain": "your-interactive-block",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",
"render": "file:./render.php",
"viewScriptModule": "file:./view.js"
}
以下欄位對於互動式區塊至關重要:
apiVersion:3是區塊 API 的最新版本,支援最新的區塊功能,例如指令碼模組。supports:指定區塊支援的功能。"interactivity": true表示支援互動式 API。render:指定負責前端渲染的 PHP 檔案。您可以在此檔案中新增使區塊具有互動性的指令。viewScriptModule:指定包含互動邏輯的 JavaScript 檔案。此檔案僅在前端載入,並且僅當頁面包含互動式區塊時才會載入。
render.php
render.php 檔案用於構建動態區塊的標記。要使您的區塊具有互動性,您需要新增屬性以使區塊的 DOM 元素具有互動性。
初始專案中的 render.php 檔案如下所示:
<?php /** * PHP file to use when rendering the block type on the server to show on the front end. * * The following variables are exposed to the file: * $attributes (array): The block attributes. * $content (string): The block default content. * $block (WP_Block): The block instance. * * @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render */ // Generates a unique id for aria-controls. $unique_id = wp_unique_id( 'p-' ); // Adds the global state. wp_interactivity_state( 'create-block', array( 'isDark' => false, 'darkText' => esc_html__( 'Switch to Light', 'your-interactive-block' ), 'lightText' => esc_html__( 'Switch to Dark', 'your-interactive-block' ), 'themeText' => esc_html__( 'Switch to Dark', 'your-interactive-block' ), ) ); ?> <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" data-wp-class--dark-theme="state.isDark" > <button data-wp-on--click="actions.toggleTheme" data-wp-text="state.themeText" ></button> <button data-wp-on--click="actions.toggleOpen" data-wp-bind--aria-expanded="context.isOpen" aria-controls="<?php echo esc_attr( $unique_id ); ?>" > <?php esc_html_e( 'Toggle', 'your-interactive-block' ); ?> </button> <p id="<?php echo esc_attr( $unique_id ); ?>" data-wp-bind--hidden="!context.isOpen" > <?php esc_html_e( 'Your Interactive Block - hello from an interactive block!', 'your-interactive-block' ); ?> </p> </div>
以下是這段程式碼的功能:
wp_interactivity_state:獲取和/或設定 Interactivity API 儲存的初始全域性狀態。data-wp-interactive:在 DOM 元素及其子元素上啟用 Interactivity API。其值必須是您的外掛或區塊的唯一名稱空間。wp_interactivity_data_wp_context():生成data-wp-context指令,該指令為特定的 HTML 節點及其子元素提供本地狀態。data-wp-watch:在節點建立時以及狀態或上下文發生更改時執行回撥函式。data-wp-class--dark-theme:向 HTML 元素新增或移除dark-theme類。data-wp-on--click:在點選事件發生時同步執行程式碼。data-wp-text:設定 HTML 元素的內部文字。data-wp-bind--aria-expanded和data-wp-bind--hidden:根據布林值或字串值,為相應的元素設定 HTML 屬性(aria-expanded和hidden)。
view.js
此檔案定義了包含區塊行為所需邏輯和資料的 Store,包括狀態、操作和回撥。
以下是啟動專案生成的 view.js 檔案:
/**
* WordPress dependencies
*/
import { store, getContext } from '@wordpress/interactivity';
const { state } = store( 'create-block', {
state: {
get themeText() {
return state.isDark ? state.darkText : state.lightText;
},
},
actions: {
toggleOpen() {
const context = getContext();
context.isOpen = ! context.isOpen;
},
toggleTheme() {
state.isDark = ! state.isDark;
},
},
callbacks: {
logIsOpen: () => {
const { isOpen } = getContext();
// Log the value of `isOpen` each time it changes.
console.log( `Is open: ${ isOpen }` );
},
},
} );
store:用於建立和註冊程式碼塊全域性狀態和邏輯的主要函式。getContext:在 actions 和 callbacks 中使用,用於訪問觸發事件的 DOM 元素的本地狀態(context)。state:定義程式碼塊的全域性響應式資料。actions:包含定義邏輯和更改狀態的函式。callbacks:包含響應特定事件或狀態更改而自動執行的函式。
內容可能有點多,但別擔心!閱讀以下章節後,一切都會變得清晰明瞭。
現在,讓我們來了解互動 API 的關鍵概念:directives、store、state、actions 和 callbacks。
互動API指令
與其他前端庫(例如 Alpine.js 和 Vue.js)一樣,互動 API 使用特殊的 HTML 屬性,使您能夠響應頁面上的事件、更新應用程式的狀態、操作 DOM、應用 CSS 樣式、處理使用者輸入等等。
這些屬性被稱為 directives,它們允許你將標記程式碼與底層 JavaScript 邏輯連線起來。
以下列出了你最常用的指令。
| 功能分類 | 指令名稱 | 功能描述 |
|---|---|---|
| 啟用/名稱空間 | data-wp-interactive |
啟用該元素及其子元素的API互動能力,需設定為外掛唯一識別符號 |
| 區域性狀態 | data-wp-context |
為當前元素及其子元素提供區域性狀態(”context”),接受JSON物件(建議透過 PHP 的 wp_interactivity_data_wp_context() 在 render.php 中設定) |
| 屬性繫結 | data-wp-bind--[attribute] |
根據響應式狀態或上下文值(布林/字串)設定HTML屬性(如 disabled、 value) |
| 文字操作 | data-wp-text |
設定元素的innerText內容,僅接受字串型別資料 |
| CSS類切換 | data-wp-class--[classname] |
根據布林值新增/移除CSS類(如:data-wp-class–active=”state.isActive”) |
| 內聯樣式 | data-wp-style--[css-property] |
根據布林值設定/移除內聯樣式屬性(如:data-wp-style–color=”state.textColor”) |
| 事件處理 | data-wp-on--[event] |
響應標準DOM事件(如 click、 mouseover)執行程式碼 |
| 初始化執行 | data-wp-init |
僅在節點建立時執行一次回撥函式 |
| 狀態監聽 | data-wp-watch |
節點建立時及狀態/上下文變化時執行回撥函式 |
| 列表迭代 | data-wp-each |
動態渲染元素列表(需配合鍵值管理使用) |
如需檢視完整的指令列表,請參閱 Interactivity API 開發說明和 API 參考文件。
全域性狀態、區域性上下文和派生狀態
在使用 Interactivity API 之前,您必須熟悉前端開發中狀態管理的基本概念。經常使用 React、Vue 或 Angular 進行開發的開發者應該已經熟悉這些概念。對於這些技術的新手,以下是一些通用定義,可能會有所幫助。
全域性狀態
全域性狀態(Global state)是指應用程式幾乎所有元件都可以訪問的一組資料。例如,在 Interactivity API 中,全域性狀態會影響頁面上的所有互動模組,使它們保持同步。例如,當使用者將產品新增到購物車時,購物車模組會同步更新。
使用 Interactivity API 時,您應該使用 wp_interactivity_state() 函式在伺服器端設定全域性狀態的初始值。在上述入門專案中,該函式在 render.php 檔案中按如下方式使用:
// Adds the global state. wp_interactivity_state( 'create-block', array( 'isDark' => false, 'darkText' => esc_html__( 'Switch to Light', 'your-interactive-block' ), 'lightText' => esc_html__( 'Switch to Dark', 'your-interactive-block' ), 'themeText' => esc_html__( 'Switch to Dark', 'your-interactive-block' ), ) );
此函式接受兩個引數:
- 儲存名稱空間的唯一識別符號。在本例中,該識別符號為
create-block。 - 一個資料陣列,如果存在現有儲存名稱空間,則該陣列中的資料將被合併。
然後,使用初始全域性狀態值來渲染頁面。您可以透過在指令屬性值中使用 state 直接訪問全域性狀態值,如下面的程式碼所示:
<button data-wp-on--click="actions.toggleTheme" data-wp-text="state.themeText"></button>
store() 函式提供了從 JavaScript 訪問全域性狀態的主要入口點,但僅限於選定的名稱空間。回到初始專案程式碼,store() 函式在 view.js 檔案中的使用方式如下:
import { store, getContext } from '@wordpress/interactivity';
const { state } = store( 'create-block', {
state: { ... },
actions: { ... },
callbacks: { ... },
} );
要訪問全域性狀態,可以使用 state 屬性:
actions: {
toggleTheme() {
state.isDark = ! state.isDark;
},
},
本地上下文
本地上下文(Local context)是指只有特定元件及其直接子元件才能訪問的資料。WordPress 互動式區塊為其自身及其巢狀元素提供獨立的狀態。
使用互動 API 時,您可以使用 getContext() 函式訪問本地上下文。以示例專案為例,當使用者點選切換按鈕時,會觸發 toggleOpen() 操作,從而訪問元件的本地上下文:
actions: {
toggleOpen() {
const context = getContext();
context.isOpen = ! context.isOpen;
},
},
getContext():獲取元件的本地狀態物件。該物件的屬性在元件標記(render.php)中使用wp_interactivity_data_wp_context()函式定義。context.isOpen = ! context.isOpen;:切換元件本地上下文中isOpen屬性的值。
派生狀態
派生狀態(Derived state)是指根據現有的全域性或本地狀態動態計算的資料。
例如,請檢視 view.js 檔案中的程式碼,特別是以下部分:
const { state } = store( 'create-block', {
state: {
get themeText() {
return state.isDark ? state.darkText : state.lightText;
},
},
...
}
此程式碼塊定義了在 create-block 名稱空間中定義的全域性狀態下的 themeText 派生狀態。
get themeText()不是一個固定值,而是一個每次嘗試讀取themeText屬性時都會執行的函式。它不應該像普通函式一樣呼叫,因為互動 API 將其視為狀態屬性,並在其他狀態屬性的值發生變化時自動重新計算其值。在上面的程式碼中,每次isDark屬性值發生變化時,themeText屬性值都會重新計算。如果state.isDark為true,則themeText取state.darkText的值;否則,取state.lightText的值。
有關本節所述概念的更全面概述,請參閱“理解全域性狀態、區域性上下文和派生狀態”。
動作和回撥
動作和回撥決定了對使用者互動和狀態變化的響應。
互動式模組的 actions 部分包含響應使用者觸發事件而執行的函式。這些函式主要用於修改元件的區域性或全域性狀態。以下程式碼取自 view.js 檔案:
actions: {
toggleOpen() {
const context = getContext();
context.isOpen = ! context.isOpen;
},
...
},
- 在本程式碼段中,
toggleOpen()函式使用getContext()來訪問觸發操作以切換isOpen屬性值的程式碼塊的本地上下文。
類似地,您也可以訪問全域性狀態:
actions: {
...,
toggleTheme() {
state.isDark = ! state.isDark;
},
},
toggleTheme()函式直接訪問全域性狀態物件並更改isDark屬性的值。
操作透過 data-wp-on--[event] 指令觸發。例如,在 render.php 檔案中,您會找到以下按鈕:
<button aria-controls="<?php echo esc_attr( $unique_id ); ?>" >
- 在這段 HTML 程式碼中,
data-wp-on--click屬性會在使用者點選切換按鈕時啟用toggleOpen操作。
callbacks 函式部分包含一些函式,這些函式會在依賴的資料發生變化時自動執行。它們的目的是響應狀態變化而產生副作用。
在 create-block-interactive-template 生成的基礎專案中,你會找到以下回撥函式:
callbacks: {
logIsOpen: () => {
const { isOpen } = getContext();
// Log the value of `isOpen` each time it changes.
console.log( `Is open: ${ isOpen }` );
},
},
logIsOpen函式使用isOpen變數,該變數位於本地上下文中。- 回撥函式使用
getContext()獲取isOpen的值。 - 每次
isOpen的值發生變化時,該函式都會向瀏覽器控制檯輸出一條訊息。

控制檯會顯示一條訊息,告知使用者本地上下文已發生更改。
如何構建互動式模組
現在我們已經掌握了理論知識,是時候開始編寫程式碼了!在本指南的第二部分,您將學習如何建立一個互動式模組,使使用者能夠將產品新增到理想的購物車中,數量和總計會自動更新。這是一個演示示例,但我們希望它能幫助您清楚地瞭解如何使用狀態、操作和回撥。

編輯器中的互動式模組
我們將使用 create-block-interactive-template 建立一個名為“Interactive Counter”的模組。首先,開啟命令列工具並輸入以下命令:
npx @wordpress/create-block interactive-counter --template @wordpress/create-block-interactive-template
接下來,導航到你的新專案目錄並執行第一次構建。
cd interactive-counter && npm run build
現在用程式碼編輯器開啟專案。在 /src 目錄下,找到 block.json 檔案。它應該類似於這樣:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "create-block/interactive-counter",
"version": "0.1.0",
"title": "Interactive Counter",
"category": "widgets",
"icon": "media-interactive",
"description": "An interactive block with the Interactivity API.",
"supports": {
"interactivity": true
},
"textdomain": "interactive-counter",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",
"render": "file:./render.php",
"viewScriptModule": "file:./view.js"
}
您可以隨意自定義,但請確保不要修改上述基本欄位。
edit.js檔案
下一步是建立將在編輯器中顯示的區塊。為此,您需要編輯 /src/edit.js 檔案。開啟該檔案並按如下方式修改:
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit({ attributes, setAttributes }) {
const blockProps = useBlockProps();
const products = [
{ id: 'product1', name: __('Product 1', 'interactive-counter'), price: 10.00 },
{ id: 'product2', name: __('Product 2', 'interactive-counter'), price: 15.00 },
{ id: 'product3', name: __('Product 3', 'interactive-counter'), price: 20.00 },
];
return (
<div {...blockProps}>
<h3>{__('Shopping Cart', 'interactive-counter')}</h3>
<ul>
{products.map((product) => (
<li key={product.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '10px' }}>
<span style={{ flex: 1 }}>{product.name} - ${product.price.toFixed(2)}</span>
<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
<button disabled>-</button>
<span>0</span>
<button disabled>+</button>
</div>
<span style={{ flex: 1, textAlign: 'right' }}>
{__('Subtotal:', 'interactive-counter')} $0.00
</span>
</li>
))}
</ul>
<div style={{ borderTop: '1px solid #ccc', paddingTop: '15px' }}>
<p style={{ display: 'flex', justifyContent: 'space-between' }}>
<strong>{__('Subtotal:', 'interactive-counter')}</strong>
<span>$0.00</span>
</p>
<p style={{ display: 'flex', justifyContent: 'space-between' }}>
<strong>{__('Tax (22%):', 'interactive-counter')}</strong>
<span>$0.00</span>
</p>
<p style={{ display: 'flex', justifyContent: 'space-between' }}>
<strong>{__('Total:', 'interactive-counter')}</strong>
<span>$0.00</span>
</p>
</div>
<p>{__('Quantities and totals will be interactive in the frontend.', 'interactive-counter')}</p>
</div>
);
}
這段程式碼會在後端生成一個自定義區塊。該區塊僅在前端可互動。有關 /src/edit.js 檔案的更多詳細資訊,請參閱我們的 Gutenberg 區塊開發指南。
render.php檔案
接下來要編輯的檔案是 /src/render.php。開啟該檔案,並將現有程式碼替換為以下程式碼:
<?php
/**
* Render callback for the interactive-counter block.
*/
$products = [
['id' => 'product1', 'name' => __('Product 1', 'interactive-counter'), 'price' => 10.00],
['id' => 'product2', 'name' => __('Product 2', 'interactive-counter'), 'price' => 15.00],
['id' => 'product3', 'name' => __('Product 3', 'interactive-counter'), 'price' => 20.00],
];
// Initialize global state
wp_interactivity_state('interactive-counter', [
'products' => array_map(function ($product) {
return [
'id' => $product['id'],
'name' => $product['name'],
'price' => $product['price'],
'quantity' => 0,
'subtotal' => '0.00',
];
}, $products),
'vatRate' => 0.22,
]);
這段程式碼的作用如下:
- 首先,它建立一個硬編碼的產品陣列。每個產品都有一個 ID、一個名稱和一個價格。
- 接下來,它使用
wp_interactivity_state初始化全域性狀態。第一個引數是商店名稱,必須與view.js中使用的名稱一致。 - 然後,它將之前的產品陣列對映到一個新的
products陣列,並在原始陣列的屬性中新增數量和小計。這個新陣列提供了您將在view.js中使用的資料結構。 vatRate設定稅額計算的預設值。
接下來,將以下內容新增到上面的程式碼中:
<div <?php echo get_block_wrapper_attributes(); ?>>
<h3><?php echo esc_html__('Cart', 'interactive-counter'); ?></h3>
<ul>
<?php foreach ($products as $index => $product) : ?>
<li data-wp-context='{
"productId": "<?php echo esc_attr($product['id']); ?>",
"quantity": 0,
"subtotal": "0.00"
}'
data-wp-bind--data-wp-context.quantity="state.products[<?php echo $index; ?>].quantity"
data-wp-bind--data-wp-context.subtotal="state.products[<?php echo $index; ?>].subtotal">
<span class="product-name"><?php echo esc_html($product['name']); ?> - $<?php echo esc_html(number_format($product['price'], 2)); ?></span>
<div class="quantity-controls">
<button>-</button>
<span>0</span>
<button>+</button>
</div>
<span class="product-subtotal">
<?php echo esc_html__('Subtotal:', 'interactive-counter'); ?>
$<span>0.00</span>
</span>
</li>
<?php endforeach; ?>
</ul>
<div class="totals">
<p>
<strong><?php echo esc_html__('Subtotal:', 'interactive-counter'); ?></strong>
$ <span>0.00</span>
</p>
<p>
<strong><?php echo esc_html__('Tax (22%):', 'interactive-counter'); ?></strong>
$ <span>0.00</span>
</p>
<p>
<strong><?php echo esc_html__('Total:', 'interactive-counter'); ?></strong>
$ <span>0.00</span>
</p>
</div>
</div>
這段程式碼的作用如下:
div容器中的get_block_wrapper_attributes()函式是一個 WordPress 函式,用於生成區塊的標準屬性。在本例中,它生成了類屬性wp-block-create-block-interactive-counter。data-wp-interactive屬性使該區塊具有互動性。data-wp-init屬性觸發了view.js中定義的初始化回撥。foreach迴圈為products陣列中的每個產品生成一個列表項。data-wp-context定義了區塊的本地上下文。data-wp-bind將data-wp-context.quantity的值繫結到全域性屬性state.products[$index].quantity。- 下一行程式碼也做了同樣的處理,用於計算小計。
- 以下兩個按鈕透過
data-wp-on--click屬性啟用遞減和遞增操作。 span元素中的data-wp-text屬性會根據context.quantity的當前值更新元素的內容。
其餘程式碼無需贅述,我們繼續檢視下一個檔案。
view.js檔案
此檔案包含互動式模組的邏輯。
import { store, getContext } from '@wordpress/interactivity';
store('interactive-counter', {
state: {
get subtotal() {
const { products } = store('interactive-counter').state;
return products
.reduce((sum, product) => sum + product.price * (product.quantity || 0), 0)
.toFixed(2);
},
get vat() {
const { subtotal, vatRate } = store('interactive-counter').state;
return (subtotal * vatRate).toFixed(2);
},
get total() {
const { subtotal, vat } = store('interactive-counter').state;
return (parseFloat(subtotal) + parseFloat(vat)).toFixed(2);
},
},
actions: {
increment: () => {
const context = getContext();
const { products } = store('interactive-counter').state;
const product = products.find(p => p.id === context.productId);
if (product) {
product.quantity = (product.quantity || 0) + 1;
product.subtotal = (product.price * product.quantity).toFixed(2);
context.quantity = product.quantity;
context.subtotal = product.subtotal;
console.log(`Incremented ${context.productId}:`, { quantity: product.quantity, subtotal: product.subtotal, context });
} else {
console.warn('Product not found:', context.productId);
}
},
decrement: () => {
const context = getContext();
const { products } = store('interactive-counter').state;
const product = products.find(p => p.id === context.productId);
if (product && (product.quantity || 0) > 0) {
product.quantity -= 1;
product.subtotal = (product.price * product.quantity).toFixed(2);
context.quantity = product.quantity;
context.subtotal = product.subtotal;
console.log(`Decremented ${context.productId}:`, { quantity: product.quantity, subtotal: product.subtotal, context });
} else {
console.warn('Cannot decrement:', context.productId, product?.quantity);
}
},
},
callbacks: {
init: () => {
const { products } = store('interactive-counter').state;
products.forEach((product, index) => {
product.quantity = 0;
product.subtotal = '0.00';
console.log(`Initialized product ${index}:`, { id: product.id, quantity: product.quantity, subtotal: product.subtotal });
});
},
},
});
此檔案定義了 interactive-counter 名稱空間的儲存。它管理狀態、操作和回撥:
store('interactive-counter', {
state: { ... },
actions: { ... },
callbacks: { ... },
});
讓我們仔細看看。
state:定義了三個計算狀態屬性(getter):subtotal、vat和total。這些函式從全域性狀態中檢索值並計算要返回的值。actions:定義了兩個在事件發生時執行的函式:increment和Decrement。這些函式從全域性狀態中檢索products陣列,根據context.productId從本地上下文中檢索當前產品,更新當前產品的屬性值(quantity和subtotal),並將本地上下文與新值同步。callbacks:定義了一個用於初始化的init回撥函式。
下圖顯示了前端的互動式模組。

使用互動式 API 構建的互動式計數器
小結
在本文中,我們介紹了 WordPress 互動式 API 的主要特性。我們深入探討了全域性狀態、區域性上下文、指令、操作和回撥等關鍵概念。您學習瞭如何使用 @wordpress/create-block-interactive-template 從頭開始建立一個互動式區塊,並透過建立一個與使用者輸入互動的真實區塊來實踐所學。
我們希望本文能為您提供必要的工具和知識,幫助您使用 WordPress 互動式 API 建立出色、動態且互動式的 WordPress 網站。
Happy coding!

評論留言