塊可以在它們之間共享數(shù)據(jù)、操作和回調(diào)。這使得塊之間的通信更加簡單并且不易出錯。例如,單擊“添加到購物車”塊可以無縫更新單獨(dú)的“購物車”塊。為了更好地理解其背后的原因,您可以查看原始提案,其中有更詳細(xì)的解釋。有關(guān)它的更多信息可以在合并公告、狀態(tài)更新帖子和交互 API 的Trac 票證中找到。本文涵蓋了 6.5 中包含的 API 以及如何使用交互 API。

如何使用交互 API 創(chuàng)建交互

需要強(qiáng)調(diào)的是,區(qū)塊創(chuàng)建*工作流程***不會改變**。到目前為止,WordPress 一直有意對區(qū)塊前端使用的不同解決方案不發(fā)表意見。交互 API 改變了這一點(diǎn)。它添加了一種新的標(biāo)準(zhǔn)方法,可以輕松地將前端交互性添加到塊,同時處理塊編輯器的 API 保持不變。您首先需要通過在文件中的supports內(nèi)添加交互屬性來聲明其與API的兼容性block.json

"supports": {
"interactivity": true
},

交互 API 腳本需要使用WordPress 6.5 中的新腳本模塊,因此塊應(yīng)使用 viewScriptModule將JavaScript排入隊(duì)列:

// block.json
{
...
"viewScriptModule": "file:./view.js"
}

考慮到這一點(diǎn),為了向由交互 API 提供支持的塊添加交互性,開發(fā)人員需要:

  1. 向標(biāo)記添加指令以向塊添加特定交互。
  2. 使用交互邏輯(狀態(tài)、操作或回調(diào))創(chuàng)建存儲。

我們用一個簡單的例子來解釋一下:一個顯示和隱藏一些文本的按鈕。當(dāng)按鈕隱藏或顯示時,我們還可以在控制臺中發(fā)送一條消息。

1. 添加指令

指令是添加到塊標(biāo)記中的自定義屬性,以向其 DOM 元素添加交互。它們被放置在 render.php 文件中(對于動態(tài)塊)。第一步是添加指令data-wp-interactive。這用于“激活” DOM 元素及其子元素中的交互 API,其值必須是插件或塊的唯一命名空間:

<div data-wp-interactive="myPlugin">
<!-- Interactivity API zone -->
</div>

其余指令可以添加所需的交互。

// render.php
$context = array('isOpen' => false);
<div
<?php echo get_block_wrapper_attributes(); ?>
<?php echo wp_interactivity_data_wp_context($context) ?>
data-wp-interactive='myPlugin'
data-wp-watch="callbacks.logIsOpen"
>
<button
data-wp-on--click="actions.toggle"
data-wp-bind--aria-expanded="context.isOpen"
>
Toggle
</button>
<p id="p-1" data-wp-bind--hidden="!context.isOpen">
This element is now visible!
</p>
</div>

此外,還可以使用HTML 標(biāo)簽處理器動態(tài)注入指令。如果您還不明白它是如何工作的,請不要擔(dān)心。到目前為止,重要的部分是上面的示例使用wp-on和等指令向HTMLwp-bind添加交互性。這是 WordPress 6.5 中可用的指令列表:您可以在相關(guān)鏈接中找到每個指令的更深入解釋以及如何使用它的示例。

2. 創(chuàng)建商店

存儲用于創(chuàng)建將指令與該邏輯內(nèi)使用的數(shù)據(jù)鏈接起來的邏輯。所有存儲都由唯一的命名空間引用,分離邏輯并避免不同存儲屬性和函數(shù)之間的名稱沖突。如果使用相同的命名空間定義了多個存儲,它們將被合并到一個存儲中。存儲通常在每個塊的 view.js 文件中創(chuàng)建,盡管狀態(tài)可以在后端初始化,例如在塊的渲染文件中。狀態(tài)是一個全局對象,可用于頁面的所有 HTML 節(jié)點(diǎn)。它是由store()函數(shù)定義的。如果您只需要節(jié)點(diǎn)及其子節(jié)點(diǎn)的本地狀態(tài),請檢查上下文定義。該對象可以接受任何屬性,為了保持項(xiàng)目之間的一致性,建議使用此約定。

回到我們的示例,這可能是一個塊中的簡單存儲,已添加全局狀態(tài)以獲得存儲外觀的完整示例。

// view.js
import { store, getContext } from "@wordpress/interactivity";
const { state } = store( 'myPlugin', {
state: {
likes: 0,
getDoubleLikes() {
return 2 * state.likes;
}
},
actions: {
toggle: () => {
const context = getContext();
context.isOpen = !context.isOpen;
},
},
callbacks: {
logIsOpen: () => {
const context = getContext();
// Log the value of isOpen each time it changes. console.log(Is open: ${context.isOpen}); }, }, });

在某些情況下,商店中可能只定義了操作和回調(diào)。DOM 元素通過指令連接到存儲在狀態(tài)和上下文中的數(shù)據(jù)。如果狀態(tài)或上下文更改指令中的數(shù)據(jù)將對這些更改做出反應(yīng),則會相應(yīng)地更新 DOM(參見圖表)。

創(chuàng)建商店時,有一些重要事項(xiàng)需要注意:

使用派生狀態(tài)

派生狀態(tài)使用getter返回狀態(tài)的計算版本。它可以訪問狀態(tài)和上下文。

// 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,
},
},
} );

通過解構(gòu)訪問存儲

存儲包含所有存儲屬性,例如狀態(tài)、操作或回調(diào)。它們由store()調(diào)用返回,因此您可以通過解構(gòu)它們來訪問它們:

const { state, actions, callbacks } = store( "myPlugin", {
// ...
} );

請注意,上下文不是存儲的一部分,而是通過getContext函數(shù)訪問的。如果您想更深入地了解該函數(shù)的工作原理,請隨時查看此處的store()函數(shù)文檔。

異步操作

異步操作應(yīng)該使用生成器函數(shù)而不是 async/await 或 Promise。交互 API 需要能夠跟蹤異步行為,以便恢復(fù)正確的范圍。否則,getContext如果與異步操作同時更新,則可能會返回過時的值。不用等待承諾,而是從生成器函數(shù)中生成它,并且交互 API 將處理等待其完成的情況。所以,而不是:

store("myPlugin", {
state: {
get isOpen() {
return getContext().isOpen;
},
},
actions: {
someAction: async () => {
state.isOpen; // This is the expected context.
await longDelay();
state.isOpen; // This may not get the proper context unless it's properly restored.
},
},
});

function longDelay() {
return new Promise( ( resolve ) => {
setTimeout( () => resolve(), 3_000 );
} );
}

商店應(yīng)該是:

store("myPlugin", {
state: {
get isOpen() {
return getContext().isOpen;
},
},
actions: {
someAction: function* () {
state.isOpen; // This is the expected context.
yield longDelay(); // With generators, the caller controls when to resume this function.
state.isOpen; // This context is correct because the scope was restored before resuming after the yield.
},
},
});

使用其他命名空間

交互塊可以在它們之間共享數(shù)據(jù),除非它們是私有存儲。

指令

為了訪問指令中不同命名空間的存儲,請在指令值之前添加命名空間。例如:

為了訪問指令中不同命名空間的存儲,請在指令值之前添加命名空間。例如:

<!-- This accesses the current store -->
<div data-wp-class--is-hidden="state.isHidden"></div>

<!-- This accesses the "otherPlugin" store -->
<button data-wp-on--click="otherPlugin::actions.addToCart>Button</button>

語境

可以通過提供所需的命名空間作為參數(shù)來訪問來自不同命名空間的上下文getContext( namespace )

import { getContext } from "@wordpress/interactivity";
const otherPluginContext = getContext( "otherPlugin" );

店鋪

與上下文一樣,可以通過將所需的命名空間作為參數(shù)傳遞來訪問不同的存儲:

const { state: otherState, actions: otherActions } = store( "otherPlugin" );

私人商店

可以“鎖定”存儲以防止從其他名稱空間訪問其內(nèi)容。為此,請在 store() 調(diào)用中將 lock 選項(xiàng)設(shè)置為 true,如下例所示。設(shè)置鎖后,具有相同鎖定命名空間的 store() 后續(xù)執(zhí)行將引發(fā)錯誤,這意味著該命名空間只能在第一次 store() 調(diào)用返回其引用的位置進(jìn)行訪問。這對于想要隱藏部分插件存儲以使擴(kuò)展程序無法訪問的開發(fā)人員特別有用。

const { state } = store("myPlugin/private", {
state: {
messages: [ "private message" ]
}
},
{ lock: true }
);

// The following call throws an Error!
store( "myPlugin/private", { /* store part */ } );

還有一種方法可以解鎖私有存儲:您可以使用字符串作為鎖定值,而不是傳遞布爾值。然后可以在對同一名稱空間的后續(xù) store() 調(diào)用中使用這樣的字符串來解鎖其內(nèi)容。只有帶有鎖定字符串的代碼才能訪問受保護(hù)的存儲區(qū)。這對于跨多個文件定義的復(fù)雜存儲非常有用。

const { state } = store("myPlugin/private", {
state: {
messages: [ "private message" ]
}
},
{ lock: PRIVATE_LOCK }
);

// The following call works as expected.
store( "myPlugin/private", { /* store part */ }, { lock: PRIVATE_LOCK } );

交互 API 客戶端方法

以下方法適用于 JavaScript,由 WordPress 6.5 中提供的 wordpress/interactivity 腳本模塊提供。

獲取上下文()

data-wp-context可以使用 getContext 函數(shù)檢索使用該屬性定義的上下文:

const { state } = store( "myPlugin", {
actions: {
someAction() {
const context = getContext();
const otherPluginContext = getContext( 'otherPlugin' );
// ...
}
}
} );

獲取元素()

檢索正在評估存儲中的函數(shù)的元素的表示。該表示形式是只讀的,并且包含對 DOM 元素及其屬性的引用。手冊說明。

獲取配置()

通過函數(shù)檢索先前在服務(wù)器中定義的配置對象wp_interactivity_config()。配置在客戶端上是不可變的,無法修改。

店鋪()

創(chuàng)建用于將數(shù)據(jù)和操作與其各自的指令鏈接起來的存儲。

withScope()

操作可以取決于調(diào)用它們時的范圍,例如,當(dāng)您調(diào)用getContext()或時getElement()。當(dāng)交互 API 運(yùn)行時執(zhí)行回調(diào)時,范圍會自動設(shè)置。但是,如果您從運(yùn)行時未執(zhí)行的回調(diào)中調(diào)用操作(例如在回調(diào)中)setInterval(),則需要確保正確設(shè)置范圍。使用該withScope()函數(shù)可確保在這些情況下正確設(shè)置范圍。一個示例,如果actions.nextImage沒有包裝器,將觸發(fā)未定義的錯誤:

store('mySliderPlugin', {
callbacks: {
initSlideShow: () => {
setInterval(
withScope( () => {
actions.nextImage();
} ),
3_000
);
}
},
})

交互API服務(wù)器功能

這些是交互 API 包含的 PHP 函數(shù):

wp_interactivity_state( $store_namespace, $state )

它用于初始化服務(wù)器上的狀態(tài)并確保其發(fā)送的 HTML 與客戶端 Hydration 后的 HTML 相同。它還允許您使用任何 WordPress API,例如核心翻譯。

// render.php

wp_interactivity_state( "movies", array(
"1" => array(
"id" => "123-abc",
"movieName" => __("someMovieName", "textdomain")
),
) );

它接收兩個參數(shù),一個帶有將用作引用的名稱空間的字符串和一個包含值的關(guān)聯(lián)數(shù)組。此函數(shù)中定義的狀態(tài)將與 view.js 文件中定義的存儲合并。

wp_interactivity_data_wp_context( $context, $ *store_namespace* )

生成一個data-wp-context準(zhǔn)備好在服務(wù)器端呈現(xiàn)的屬性。除了手動寫入 JSON 字符串時可能出現(xiàn)的任何錯誤之外,此函數(shù)會對數(shù)組進(jìn)行轉(zhuǎn)義以防止外部攻擊。$context是一個包含上下文的鍵和值的數(shù)組。$*store_namespace*允許引用不同的存儲,默認(rèn)為空。

<?php
$context = array(
'id' => $post_id,
'show' => true,
);
?>
<div <?php echo wp_interactivity_data_wp_context($context) ?> >
My interactive div
</div>

將返回

<div data-wp-context="{ "id": 1, "show": "true" } ">
My interactive div
</div>

wp_interactivity_config( $store_namespace, $config )

設(shè)置或獲取交互存儲的配置。客戶端可以讀取配置的不可變副本。將配置視為可以影響整個站點(diǎn)并且不會在客戶端交互時更新的全局設(shè)置。例如,確定站點(diǎn)是否可以處理客戶端導(dǎo)航。

<?php
// Sets configuration for the 'myPlugin' namespace.
wp_interactivity_config( 'myPlugin', array( 'setting' => true ) );

// Gets the current configuration for the 'myPlugin' namespace.
$config = wp_interactivity_config( 'myPlugin' );

可以在客戶端中檢索此配置:

// view.js

const { setting } = getConfig();
console.log( setting ); // Will log true.

wp_interactivity_process_directives( $html )

處理 HTML 內(nèi)容中的指令,并在必要時更新標(biāo)記。這是交互 API 的核心功能。它是公開的,因此可以處理任何 HTML,而不僅僅是塊。For 帶有supports.interactivity,指令的塊會被自動處理。在這種情況下,開發(fā)人員不需要調(diào)用wp_interactivity_process_directives

<?php
$html_content = '<div data-wp-text="myPlugin::state.message"></div>';
wp_interactivity_state( 'myPlugin', array( 'message' => 'hello world!' ) );

// Process directives in HTML content.
$processed_html = wp_interactivity_process_directives( $html_content );
// output: <div data-wp-text="myPlugin::state.message">hello world!</div>

文章轉(zhuǎn)自微信公眾號@開源應(yīng)用

熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
3000+提示詞助力AI大模型
和專業(yè)工程師共享工作效率翻倍的秘密
返回頂部
上一篇
使用 YApi 管理 API 文檔、測試、MOCK
下一篇
接口開發(fā)神器啊!YesApi這個平臺太牛了!輕松開發(fā)上百個API接口
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
欧美日韩精品免费观看视频| 亚洲国产综合色| 国产精品国产三级国产三级人妇| 免费成人av在线| 日本亚洲电影天堂| 精品少妇一区二区三区在线视频| 日韩电影网1区2区| 日韩欧美一区二区在线视频| 免费一级欧美片在线观看| 久久久久88色偷偷免费| 免费观看日韩av| 1024成人网| 欧美日韩综合在线| 国产一区在线不卡| 亚洲一区二区三区在线播放| 欧美精品欧美精品系列| 亚洲成人av中文| 亚洲丝袜美腿综合| 精品国产电影一区二区| 欧美精品免费视频| 欧美亚洲综合在线| 成人小视频在线| 日本不卡一二三| 天天综合天天做天天综合| 一区二区三区在线看| 欧美三级日韩在线| 色天使色偷偷av一区二区| 国产精品18久久久久久久久| 欧美bbbbb| 一区二区三区不卡在线观看 | 中文字幕国产一区| 亚洲精品在线观看视频| 精品伦理精品一区| 日韩欧美三级在线| 91精品综合久久久久久| 乱中年女人伦av一区二区| 免费成人结看片| 国产乱码字幕精品高清av | 欧美成人aa大片| 久久久久久夜精品精品免费| 日韩无一区二区| 欧美国产精品中文字幕| 久久综合狠狠综合| 亚洲日本电影在线| 三级在线观看一区二区| 国产精品夜夜嗨| 91啪在线观看| 欧美日韩国产小视频| 久久久99免费| 中文字幕一区二区三区乱码在线| 午夜精品久久一牛影视| 国产成人精品影视| 欧美一区二区三区在线观看| 中文字幕乱码日本亚洲一区二区| 日韩理论片网站| 国产成人亚洲综合色影视| 精品视频在线视频| 5566中文字幕一区二区电影| 亚洲午夜影视影院在线观看| 亚洲女子a中天字幕| 夜夜操天天操亚洲| 狠狠色狠狠色综合系列| 一本大道综合伊人精品热热| 国产日韩亚洲欧美综合| 欧美激情一区二区三区蜜桃视频| 亚洲成人激情综合网| 97久久精品人人做人人爽| 久久久精品欧美丰满| 国产精品夜夜爽| 欧美国产精品久久| 粉嫩av亚洲一区二区图片| 精品国产麻豆免费人成网站| 日本sm残虐另类| 欧美一区二区三区四区高清| 中文字幕在线不卡一区| 成人免费视频国产在线观看| 久久久久国色av免费看影院| 精品午夜一区二区三区在线观看| 26uuu欧美日本| 99久久精品99国产精品| 亚洲一区二区三区四区在线观看 | 久久久蜜桃精品| 99视频一区二区三区| 亚洲免费观看高清完整版在线观看 | 亚洲精品大片www| 欧美日韩一区二区三区高清| 午夜a成v人精品| 久久精品亚洲精品国产欧美kt∨| 99久久精品国产导航| 欧美aaa在线| www成人在线观看| 视频一区欧美日韩| 久久久久免费观看| 欧美丝袜第三区| 国产99久久久国产精品潘金网站| 亚洲图片欧美激情| 欧美在线看片a免费观看| 蜜臀精品一区二区三区在线观看| 国产女人18水真多18精品一级做 | 欧美xxx久久| av在线一区二区三区| 一级精品视频在线观看宜春院| 欧美日韩精品欧美日韩精品一| 成人国产一区二区三区精品| 免费精品视频在线| 亚洲电影第三页| 国产肉丝袜一区二区| 56国语精品自产拍在线观看| 色香色香欲天天天影视综合网| 水蜜桃久久夜色精品一区的特点| 欧美久久一二三四区| 国产福利精品一区| 日韩伦理免费电影| 26uuu久久天堂性欧美| 欧美日韩日日摸| 在线免费av一区| 精品视频全国免费看| 91精品啪在线观看国产60岁| 国产一区三区三区| 日韩理论电影院| 日本一区二区视频在线| 91福利视频久久久久| 国产一区二区看久久| 亚洲福利一区二区三区| 午夜精品久久久久久久99樱桃| 99在线精品观看| 国产一区在线观看麻豆| av在线不卡免费看| 在线观看国产日韩| 91麻豆精品国产91久久久使用方法| 欧美在线影院一区二区| 欧美日韩免费不卡视频一区二区三区 | 从欧美一区二区三区| 欧美色国产精品| 欧美精品一区二区三区一线天视频| 欧美三级视频在线| 精品播放一区二区| 自拍偷拍亚洲欧美日韩| 久久蜜桃一区二区| 久久综合九色综合97_久久久| 欧美天堂一区二区三区| 日韩精品在线一区| 国产精品久久网站| 午夜私人影院久久久久| 亚洲欧洲无码一区二区三区| 亚洲一区二区三区四区在线免费观看 | 亚洲精品高清在线| 狠狠色丁香婷综合久久| 国产美女视频91| 欧美精品v国产精品v日韩精品 | 福利一区二区在线观看| 欧美一区二区免费视频| 亚洲综合在线视频| 成人午夜激情片| 国产欧美日韩综合精品一区二区| 午夜精品福利一区二区三区av | 欧美夫妻性生活| 亚洲精品视频一区二区| 视频在线观看国产精品| 久久97超碰国产精品超碰| 在线日韩av片| 自拍视频在线观看一区二区| 波多野结衣在线一区| 亚洲国产成人一区二区三区| 国内外成人在线| 日韩欧美国产精品| 久久国产免费看| 2022国产精品视频| 国产高清精品在线| 亚洲女同一区二区| 欧美亚洲一区二区三区四区| 亚洲v中文字幕| 欧美人与性动xxxx| 精品一区精品二区高清| 久久久久久久久免费| 激情五月激情综合网| xnxx国产精品| 色综合久久久久综合体| 天天色天天爱天天射综合| 欧美v日韩v国产v| 国产福利不卡视频| 国产午夜亚洲精品午夜鲁丝片| 国产夫妻精品视频| 自拍偷拍亚洲综合| 精品欧美乱码久久久久久| 天堂一区二区在线| 久久女同互慰一区二区三区| 91久久免费观看| 国模无码大尺度一区二区三区| 日韩精品一区二区三区在线观看| 精品亚洲国内自在自线福利| 亚洲精品中文在线| 久久一区二区三区国产精品| 一本色道a无线码一区v| 国内精品伊人久久久久av一坑 | 欧美一区二区三区四区在线观看 | 秋霞av亚洲一区二区三| 亚洲成人av一区| 国产精品美女久久久久久久久| 3d成人h动漫网站入口|