構建自定義古騰堡區塊:權威WordPress區塊開發教程

構建自定義古騰堡區塊:權威WordPress區塊開發教程

許多人抱怨開始構建古騰堡區塊和應用程式的障礙。學習曲線陡峭,主要是由於開發環境的安裝和配置困難。此外,紮實的JavaScript、Node.js、React和Redux知識是這個相當複雜的祕訣的必備要素。

官方的WordPress區塊編輯器手冊為開發人員提供了大量資訊,但您可能會發現自己迷失在這些細節的海洋中。

值得一提的是,Gutenberg專案的首席架構師Matías Ventura在接受WP Tavern採訪時所報告的內容:

雖然有些人可以快速學習它,但這對人們來說仍然是一個很大的障礙。我認為這有幾個層次;文件在組織和演示方面可能要好一個數量級。我希望我們可以在那裡做更多的事情。

考慮到這一點,我們決定提供一個分步教程,旨在幫助我們的讀者開始使用Gutenberg區塊開發。

  1. 古騰堡區塊開發先決條件
  2. 什麼是古騰堡區塊?
  3. 設定您的WordPress開發環境
  4. 初學者區塊腳手架的演練
  5. 專案:建造你的第一個古騰堡區塊

古騰堡區塊開發先決條件

對於本教程,唯一需要的技能是對WordPress外掛開發有很好的瞭解,並且至少對HTML、CSS、JavaScript和React有基本的瞭解。

這會是一個雄心勃勃的專案嗎?你打賭它會的!

在完整性和簡單性之間找到正確的折衷方案或決定包含哪些主題和省略哪些主題並不容易。

希望中高階讀者能原諒我們沒有深入研究某些概念,例如React狀態Redux儲存高階元件等。這些主題需要額外的空間和注意力,並且可能對於開始區塊開發來說太高階了(除非您是 React 開發人員)。

出於同樣的原因,我們不會涵蓋與Gutenberg區塊開發相關的一些更高階的主題,例如動態區塊元框

有了本文結尾您將獲得的知識,您將能夠立即開始享受樂趣並提高工作效率。

一旦您開始構建區塊,您將準備好進一步提高您的技能並自行構建更高階的古騰堡區塊。

什麼是古騰堡區塊?

自2018年12月首次釋出以來,區塊編輯器在各個方面都得到了極大的改進:更強大的API、更高階的使用者介面、改進的可用性、大量新區塊、全站點編輯的首次實現等等.

簡而言之,即使古騰堡仍在大力開發中,它也已經走過了漫長的道路——如今,區塊編輯器已成為可靠的功能性頁面和網站構建器的成熟候選者。

從開發人員的角度來看,Gutenberg是一個基於React的單頁應用程式(SPA),它允許WordPress使用者在WordPress中建立、編輯和刪除內容。但是,這不應該讓您想到傳統內容編輯器的增強版。

我們想明確這一點:

Gutenberg不是常規的WYSIWYG編輯器。相反,它重新定義了WordPress中的整個編輯體驗。

在古騰堡,內容被劃分為區塊,這些區塊是使用者可以用來建立文章和頁面或整個網站的“磚塊”。

但從技術上講,什麼是區塊?

我們喜歡WordPress的定義

“區塊”是用於描述標記單元的抽象術語,這些標記單元組合在一起形成網頁的內容或佈局。這個想法將我們今天在WordPress中實現的概念與短程式碼、自定義HTML和嵌入發現結合到一個一致的API和使用者體驗中。

標題、段落、列、影象、畫廊以及構成編輯器介面的所有元素,從側邊欄面板到區塊工具欄控制元件,都是React元件。

那麼,什麼是React元件?W3Schools提供以下定義

元件是獨立且可重用的程式碼。它們的用途與JavaScript函式相同,但獨立工作並通過render()函式返回HTML。

在WordPress 5.8中使用Gutenberg區塊

在WordPress 5.8中使用Gutenberg區塊

雖然Gutenberg提供的編輯體驗與經典的WordPress編輯器相比是全新的,但WordPress將您的內容片段儲存在資料庫中的方式根本沒有改變。這是因為Gutenberg是一個在WordPress中執行的應用程式,但不會改變CMS的核心工作方式。

使用Gutenberg建立的文章(包括文章、頁面和自定義文章型別)仍儲存在wp_posts表中,與經典編輯器完全相同。

但是在使用Gutenberg建立的文章中,您會在表格中找到更多資訊,這些資訊代表了通過Classic Editor與Gutenberg建立的文章之間的根本區別。

這些資訊看起來像HTML註釋,它們有一個特定的功能:分隔區塊:

程式碼編輯器檢視中的部落格文章

程式碼編輯器檢視中的部落格文章。

區塊分隔符告訴WordPress要在螢幕上呈現什麼區塊。它們還為JSON物件中的區塊屬性提供值。這些道具決定了區塊應該在螢幕上呈現的方式:

wp_posts儲存在表中的部落格文章

wp_posts儲存在表中的部落格文章

設定您的WordPress開發環境

設定現代JavaScript開發環境需要紮實的高階技術知識,例如WebpackReactJSXBabelESLint等。

被嚇倒了?不要!WordPress社羣已經通過提供強大的工具來幫助您避免混亂的手動配置過程。

為簡單起見,我們不會在本文中介紹轉譯(不過,我們建議您在瞭解區塊開發的基礎知識後熟悉一下)。相反,我們將介紹兩種替代工具,您可以使用它們在幾分鐘內快速輕鬆地設定現代JavaScript開發環境。您可以選擇對您的專案最方便的一個。

設定JavaScript開發環境以構建Gutenberg區塊是一個三步過程:

  1. 安裝Node.js和npm
  2. 設定開發環境
  3. 設定區塊外掛

讓我們開始吧。

1. 安裝Node.js和npm

在安裝您的開發環境並註冊您的第一個區塊之前,您需要安裝Node.js和Node包管理器 (npm)。

注:Node.js是基於Chrome的V8 JavaScript引擎構建的JavaScript執行時。npm,通常被稱為Node包管理器,被認為是“世界上最大的軟體登錄檔”。

您可以通過幾種不同的方式安裝Node.js和npm。但首先,您可能需要檢查該軟體是否已安裝在您的計算機上。

為此,請啟動終端並執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
node -v
node -v
node -v

如果結果為command not found,則您的計算機上未安裝Node.js,您可以繼續安裝。

對於本文,我們選擇了最簡單的安裝選項,即Node Installer。您需要做的就是下載與您的作業系統相對應的版本並啟動安裝嚮導:

Node.js下載頁面

Node.js下載頁面

安裝Node.js後,再次在終端中執行node -v命令。您還可以執行npm -v命令以確認您有可用的npm包。

您現在配備了以下工具:

  • npxNode.js包執行器(請參閱文件)。這允許您執行npm命令而無需先安裝它。
  • npmNode.js包管理器(請參閱文件)。這用於安裝依賴項和執行指令碼。

下一步是安裝開發環境。

2. 設定你的開發環境

在本地計算機上安裝最新版本的Node.js和npm後,您將需要一個WordPress開發環境。

您可以使用本地開發環境,也可以使用官方WordPress工具。讓我們來看看這兩種選擇。

選項 1:本地開發環境

您可以選擇不同的本地開發工具,例如MAMPXAMPP

在本地環境中建立一個新的WordPress網站

在本地環境中建立一個新的WordPress網站。

選項 2:wp-env

您也可以選擇官方wp-env工具,它提供了一個本地WordPress開發環境,您可以直接從命令列啟動。Noah Alen將其定義如下

本地WordPress環境現在就像執行單個命令一樣簡單。wp-env是用於本地WordPress環境的零配置工具。它提供有關選項的決策,以便使用者可以快速啟動WordPress而不會浪費時間。事實上,我們的目標是讓所有人都能輕鬆訪問這些環境——無論您是開發人員、設計師、經理還是其他任何人。

如果您決定試一試,安裝wp-env所需的工作量很小。只需按照以下步驟操作:

第 1 步:確認Docker和Node.js安裝

為了滿足技術要求,您首先需要在您的計算機上安裝Docker和Node.js。那是因為wp-env建立了一個執行WordPress網站的Docker例項。對程式碼所做的任何更改都會立即反映在WordPress例項中。

第 2 步:從命令列安裝@wordpress/env

在您的計算機上執行Docker和Node.js,您可以繼續安裝WordPress開發環境

您可以全域性或本地安裝wp-env。要在全域性範圍內執行此操作,您需要從外掛目錄中執行以下命令(更多資訊請參見下面的“重要”通知框):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install -g @wordpress/env
npm install -g @wordpress/env
npm install -g @wordpress/env

讓我們分解一下:

提示:預設情況下,在Mac或Linux上,節點包安裝/usr/local/lib/node_modules中。

如果當前使用者對該目錄沒有寫許可權,則會發出EACCES錯誤。瞭解有關在全域性安裝包時解決EACCES許可權錯誤的更多資訊。

要確認wp-env已成功安裝,請執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
wp-env --version
wp-env --version
wp-env --version

您應該會看到當前wp-env版本,這意味著您現在可以使用外掛資料夾中的以下命令啟動環境:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
wp-env start
wp-env start
wp-env start

您可以使用以下地址訪問WordPress儀表盤:

  • http://localhost:8888/wp-admin/

預設憑據如下:

  • 使用者名稱:admin
  • 密碼:password

設定你的區塊外掛

現在您需要一個入門區塊外掛來構建。但是,無需手動建立包含所有必要檔案和資料夾的開發區塊外掛,您只需執行一個開發工具,即可提供開始區塊開發所需的所有檔案和配置。

同樣,您有幾個選項可供選擇。讓我們來看看每一個。

選項 1:使用@wordpress/create-block設定區塊外掛

@wordpress/create-block是用於建立Gutenberg區塊的官方零配置工具:

建立區塊是一種官方支援的建立區塊的方法,用於為WordPress外掛註冊區塊。它提供了一個沒有配置的現代構建設定。它生成PHP、JS、CSS程式碼以及啟動專案所需的所有其他內容。

它很大程度上受到create-react-app的啟發。向@gaearon、整個Facebook團隊和React社羣致敬。

本地環境啟動並執行後,您可以通過簡單地執行命令npx @wordpress/create-block 來設定起始區塊,它將提供建立外掛腳手架和註冊新區塊所需的所有檔案和資料夾。

讓我們執行一個測試,看看它是如何工作的。

從命令列工具導航到/wp-content/plugins/目錄並執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx @wordpress/create-block my-first-block
npx @wordpress/create-block my-first-block
npx @wordpress/create-block my-first-block

當要求確認時,輸入y繼續:

使用@wordpress/create-block建立一個區塊

使用@wordpress/create-block建立一個區塊

該過程需要一些時間。完成後,您應該得到以下響應:

區塊外掛已建立

區塊外掛已建立

現在啟動您的WordPress開發環境並轉到WordPress儀表盤中的外掛螢幕。一個名為“My First Block”的新外掛應該已新增到您的外掛列表中:

區塊外掛已成功安裝

區塊外掛已成功安裝

注:如果您使用wp-env工具並從包含外掛的目錄執行wp-env start,它將自動掛載並啟用該外掛。如果您從任何其他目錄執行wp-env start,將建立一個通用的WordPress環境(另請參閱WordPress開發站點)。

如果需要,啟用外掛,建立一個新的部落格文章,向下滾動區塊插入器到小工具部分,然後選擇你的新區塊:

使用@wordpress/create-block建立的示例區塊

使用@wordpress/create-block建立的示例區塊

現在返回終端並將當前目錄更改為my-first-block

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cd my-first-block
cd my-first-block
cd my-first-block

然後執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm start
npm start
npm start

這使您能夠在開發模式下執行外掛。要建立生產程式碼,您應該使用以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm run build
npm run build
npm run build

選項 2:使用create-guten-block設定區塊外掛

create-guten-block是用於構建古騰堡區塊的第三方開發工具:

create-guten-block零配置開發工具包 (#0CJS) 可在幾分鐘內開發WordPress Gutenberg區塊,無需配置React、webpack、ES6/7/8/Next、ESLint、Babel等。

就像官方工具create-block一樣,create-guten-block基於create-react-app,可以幫助您輕鬆生成您的第一個區塊外掛。

該工具包提供了建立現代WordPress外掛所需的一切,包括以下內容

  • React、JSX和ES6語法支援。
  • 幕後的webpack開發/生產構建過程。
  • ES6之外的語言附加功能,例如物件擴充套件運算子。
  • 自動字首CSS,因此您不需要 -webkit或其他字首。
  • 一個構建指令碼,用於將JS、CSS和影象與源對映捆綁在一起進行生產。
  • 使用單個依賴項cgb-scripts對上述工具進行無憂更新。

請注意以下警告:

權衡是這些工具已預先配置為以特定方式工作。如果您的專案需要更多自定義,您可以“eject” 並自定義它,但是您需要維護此配置。

一旦你手頭有一個本地WordPress網站,啟動你的命令列工具,導航到你安裝的/wp-content/plugins資料夾,然後執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx create-guten-block my-first-block
npx create-guten-block my-first-block
npx create-guten-block my-first-block

在建立專案結構並下載依賴項時,您必須等待一兩分鐘:

使用create-guten-block建立Gutenberg區塊

使用create-guten-block建立Gutenberg區塊

該過程完成後,您應該會看到以下螢幕:

使用create-guten-block成功建立Gutenberg區塊

使用create-guten-block成功建立Gutenberg區塊

下一張圖片顯示了在Visual Studio Code中執行終端的專案結構:

Visual Studio Code中的區塊外掛

Visual Studio Code中的區塊外掛

現在回到您的WordPress儀表盤。外掛螢幕中應該會列出一個新專案——它是my-first-block外掛:

使用create-guten-block建立的新外掛的外掛螢幕

使用create-guten-block建立的新外掛的外掛螢幕

啟用外掛並返回終端。將當前目錄更改為my-first-block,然後執行npm start

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cd my-first-block
npm start
cd my-first-block npm start
cd my-first-block
npm start

您應該得到以下響應:

npm啟動

npm啟動

同樣,這使您能夠在開發模式下執行外掛。要建立生產程式碼,您應該使用:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm run build
npm run build
npm run build

啟用外掛並建立一個新文章或頁面,然後瀏覽您的區塊並選擇您全新的古騰堡區塊:

使用create-guten-block建立的新區塊

使用create-guten-block建立的新區塊

如需更深入的概述或出現錯誤,請參閱Ahmad Awais提供的文件

初學者區塊腳手架的演練

無論您選擇兩種開發工具中的哪一種——create-block或者create-guten-block——您現在都有一個區塊腳手架,您可以將其用作構建區塊外掛的起點。

但究竟什麼是區塊腳手架

區塊腳手架是一個簡寫術語,描述了WordPress識別區塊所需的支援目錄結構。通常,該目錄包括index.phpindex.jsstyle.css等檔案,而這些檔案又包含register_block_type.

我們選擇了官方的Create Block開發工具,因為它在Block Editor Handbook中使用。但即使您決定使用第三方工具,例如create-guten-block,您的體驗也不會有太大不同。

話雖如此,讓我們更深入地瞭解該create-block工具

仔細檢視Create Block開發工具

正如我們上面提到的,建立區塊是建立古騰堡區塊的官方命令列工具。在終端中執行@wordpress/create-block會生成註冊新區塊型別所需的PHP、JS和SCSS檔案和程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx @wordpress/create-block [options] [slug]
npx @wordpress/create-block [options] [slug]
npx @wordpress/create-block [options] [slug]
  • [slug](可選)- 用於分配區塊slug並安裝外掛
  • [options](可選)- 可用選項

預設情況下,分配一個ESNext模板。這意味著您將獲得JavaScript的下一個版本,並新增了JSX語法

如果您省略區塊名稱,該命令將以互動模式執行,使您能夠在生成檔案之前自定義多個選項:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx @wordpress/create-block
npx @wordpress/create-block
npx @wordpress/create-block

在互動模式下執行create-block

在互動模式下執行create-block

下圖顯示了使用官方建立區塊工具建立的區塊外掛的檔案結構:

使用@wordpress/create-block建立的區塊外掛的檔案和資料夾

使用@wordpress/create-block建立的區塊外掛的檔案和資料夾

話雖如此,讓我們瀏覽一下新區塊外掛的主要檔案和資料夾。

外掛檔案

使用主外掛檔案在伺服器上註冊區塊

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* Plugin Name: My First Block
* Description: Example block written with ESNext standard and JSX support – build step required.
* Requires at least: 5.8
* Requires PHP: 7.0
* Version: 0.1.0
* Author: The WordPress Contributors
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-first-block
*
* @package create-block
*/
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/writing-your-first-block-type/
*/
function create_block_my_first_block_block_init() {
register_block_type( __DIR__ );
}
add_action( 'init', 'create_block_my_first_block_block_init' );
/** * Plugin Name: My First Block * Description: Example block written with ESNext standard and JSX support – build step required. * Requires at least: 5.8 * Requires PHP: 7.0 * Version: 0.1.0 * Author: The WordPress Contributors * License: GPL-2.0-or-later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: my-first-block * * @package create-block */ /** * Registers the block using the metadata loaded from the `block.json` file. * Behind the scenes, it registers also all assets so they can be enqueued * through the block editor in the corresponding context. * * @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/writing-your-first-block-type/ */ function create_block_my_first_block_block_init() { register_block_type( __DIR__ ); } add_action( 'init', 'create_block_my_first_block_block_init' );
/**
* Plugin Name: My First Block
* Description: Example block written with ESNext standard and JSX support – build step required.
* Requires at least: 5.8
* Requires PHP: 7.0
* Version: 0.1.0
* Author: The WordPress Contributors
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-first-block
*
* @package create-block
*/
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/writing-your-first-block-type/
*/
function create_block_my_first_block_block_init() {
register_block_type( __DIR__ );
}
add_action( 'init', 'create_block_my_first_block_block_init' );

register_block_type函式使用儲存在block.json檔案中的後設資料在伺服器上註冊一個區塊型別

該函式有兩個引數:

  • 包含名稱空間的區塊型別名稱,或者block.json檔案所在資料夾的路徑,或者一個完整的WP_Block_Type物件
  • 一組區塊型別引數

在上面的程式碼中,區塊型別引數由__DIR__ 魔術常量提供。這意味著block.json檔案與外掛檔案位於同一資料夾中。

package.json檔案

package.json檔案為您的專案定義JavaScript屬性和指令碼。這是您可以安裝專案依賴項的地方。

為了更好地理解此檔案的用途,請使用您喜歡的程式碼編輯器開啟它:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"name": "my-first-block",
"version": "0.1.0",
"description": "Example block written with ESNext standard and JSX support – build step required.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"start": "wp-scripts start",
"packages-update": "wp-scripts packages-update"
},
"dependencies": {
"@wordpress/block-editor": "^7.0.1",
"@wordpress/blocks": "^11.0.1",
"@wordpress/i18n": "^4.2.1"
},
"devDependencies": {
"@wordpress/scripts": "^18.0.0"
}
}
{ "name": "my-first-block", "version": "0.1.0", "description": "Example block written with ESNext standard and JSX support – build step required.", "author": "The WordPress Contributors", "license": "GPL-2.0-or-later", "main": "build/index.js", "scripts": { "build": "wp-scripts build", "format": "wp-scripts format", "lint:css": "wp-scripts lint-style", "lint:js": "wp-scripts lint-js", "start": "wp-scripts start", "packages-update": "wp-scripts packages-update" }, "dependencies": { "@wordpress/block-editor": "^7.0.1", "@wordpress/blocks": "^11.0.1", "@wordpress/i18n": "^4.2.1" }, "devDependencies": { "@wordpress/scripts": "^18.0.0" } }
{
"name": "my-first-block",
"version": "0.1.0",
"description": "Example block written with ESNext standard and JSX support – build step required.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"start": "wp-scripts start",
"packages-update": "wp-scripts packages-update"
},
"dependencies": {
"@wordpress/block-editor": "^7.0.1",
"@wordpress/blocks": "^11.0.1",
"@wordpress/i18n": "^4.2.1"
},
"devDependencies": {
"@wordpress/scripts": "^18.0.0"
}
}

scripts 屬性是一個字典其中包含使用npm run [cmd].

在本文中,我們將使用以下命令

  • npm run build— 建立一個(壓縮的)生產版本
  • npm run start— 建立一個(未壓縮的)開發版本

dependenciesdevDependencies將包名稱對映到版本的兩個物件。dependencies在生產中需要,而devDependences僅在本地開發中需要(閱讀更多)。

唯一的預設開發依賴項是@wordpress/scripts包,它被定義為“為WordPress開發量身定製的可重用指令碼的集合”。

block.json檔案

從WordPress 5.8開始,block.json後設資料檔案是註冊區塊型別的規範方式。

擁有一個block.json檔案有幾個好處,包括提高效能和在WordPress外掛目錄上更好的可見性:

從效能的角度來看,當主題支援延遲載入資產時,使用block.json註冊的區塊將對其資產排隊進行開箱即用的優化。stylescript屬性中列出的前端CSS和JavaScript資產僅在頁面上存在區塊時才會入隊,從而減少頁面大小。

執行@wordpress/create-block命令會生成以下block.json檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"apiVersion": 2,
"name": "create-block/my-first-block",
"version": "0.1.0",
"title": "My First Block",
"category": "widgets",
"icon": "smiley",
"description": "Example block written with ESNext standard and JSX support – build step required.",
"supports": {
"html": false
},
"textdomain": "my-first-block",
"editorScript": "file:./build/index.js",
"editorStyle": "file:./build/index.css",
"style": "file:./build/style-index.css"
}
{ "apiVersion": 2, "name": "create-block/my-first-block", "version": "0.1.0", "title": "My First Block", "category": "widgets", "icon": "smiley", "description": "Example block written with ESNext standard and JSX support – build step required.", "supports": { "html": false }, "textdomain": "my-first-block", "editorScript": "file:./build/index.js", "editorStyle": "file:./build/index.css", "style": "file:./build/style-index.css" }
{
"apiVersion": 2,
"name": "create-block/my-first-block",
"version": "0.1.0",
"title": "My First Block",
"category": "widgets",
"icon": "smiley",
"description": "Example block written with ESNext standard and JSX support – build step required.",
"supports": {
"html": false
},
"textdomain": "my-first-block",
"editorScript": "file:./build/index.js",
"editorStyle": "file:./build/index.css",
"style": "file:./build/style-index.css"
}

這是預設屬性的完整列表:

  • apiVersion— 區塊使用的API版本(當前版本為2)
  • name— 包含名稱空間的區塊的唯一識別符號
  • version— 區塊的當前版本
  • title— 區塊的顯示標題
  • category— 區塊類別
  • icon— Dashicon slug或自定義SVG圖示
  • description— 在區塊檢查器中可見的簡短描述
  • supports— 一組用於控制編輯器中使用的功能的選項
  • textdomain— 外掛文字域
  • editorScript— 編輯器指令碼定義
  • editorStyle— 編輯器樣式定義
  • style— 為區塊提供替代樣式

除了上面列出的屬性之外,您還可以(並且可能會)定義一個attributes物件,提供有關您的區塊儲存的資料的資訊。在您的block.json中,您可以在鍵/值對中設定任意數量的屬性,其中鍵是屬性名稱,值是屬性定義。

看看下面的屬性定義示例:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"attributes": {
"content": {
"type": "array",
"source": "children",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"link": {
"type": "string",
"default": "https://www.wbolt.com"
}
},
"attributes": { "content": { "type": "array", "source": "children", "selector": "p" }, "align": { "type": "string", "default": "none" }, "link": { "type": "string", "default": "https://www.wbolt.com" } },
"attributes": {
"content": {
"type": "array",
"source": "children",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"link": { 
"type": "string", 
"default": "https://www.wbolt.com" 
}
},

我們將在本文後面深入研究block.json檔案,但您可能還想檢視區塊編輯器手冊以獲取有關block.json後設資料屬性的更多詳細資訊。

src資料夾

src資料夾是開發發生的地方。在該資料夾中,您將找到以下檔案:

  • index.js
  • edit.js
  • save.js
  • editor.scss
  • style.scss

index.js

index.js檔案是您的起點。在這裡,您將匯入依賴項並在客戶端上註冊區塊型別:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';
registerBlockType('create-block/my-first-block', {
edit: Edit,
save,
});
import { registerBlockType } from '@wordpress/blocks'; import './style.scss'; import Edit from './edit'; import save from './save'; registerBlockType('create-block/my-first-block', { edit: Edit, save, });
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';
registerBlockType('create-block/my-first-block', {
edit: Edit,
save,
});

第一條語句從@wordpress/blocks中匯入函式registerBlockType。以下import語句將樣式表與Editsave函式一起匯入。

registerBlockType函式在客戶端註冊元件。該函式有兩個引數:一個區塊名稱namespace/block-name(與在伺服器上註冊的相同)和一個區塊配置物件。

Edit函式提供了在區塊編輯器中呈現的區塊介面,而save函式提供了將被序列化並儲存到資料庫中的結構(閱讀更多)。

edit.js

edit.js是您構建區塊管理介面的地方:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p {...useBlockProps()}>
{__('My First Block – hello from the editor!', 'my-first-block')}
</p>
);
}
import { __ } from '@wordpress/i18n'; import { useBlockProps } from '@wordpress/block-editor'; import './editor.scss'; export default function Edit() { return ( <p {...useBlockProps()}> {__('My First Block – hello from the editor!', 'my-first-block')} </p> ); }
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p {...useBlockProps()}>
{__('My First Block – hello from the editor!', 'my-first-block')}
</p>
);
}

 

首先,它從@wordpress/i18n包中匯入函式__(這個包包含翻譯函式的JavaScript版本)、useBlockProps React鉤子editor.scss檔案。

之後,它會匯出React元件(閱讀有關匯入匯出語句的更多資訊)。

save.js

save.js檔案是我們構建要儲存到資料庫中的區塊結構的位置

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
export default function save() {
return (
<p {...useBlockProps.save()}>
{__(
'My First Block – hello from the saved content!',
'my-first-block'
)}
</p>
);
}
import { __ } from '@wordpress/i18n'; import { useBlockProps } from '@wordpress/block-editor'; export default function save() { return ( <p {...useBlockProps.save()}> {__( 'My First Block – hello from the saved content!', 'my-first-block' )} </p> ); }
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
export default function save() {
return (
<p {...useBlockProps.save()}>
{__(
'My First Block – hello from the saved content!',
'my-first-block'
)}
</p>
);
}

editor.scss和style.scss

除了指令碼之外,還有兩個SASS檔案位於src資料夾中。editor.scss檔案包含應用於編輯器上下文中區塊的樣式,而style.scss檔案包含用於在前端顯示的區塊的樣式。我們將在本指南的第二部分深入研究這些檔案。

node_modules和構建資料夾

node_modules資料夾包含節點模組及其依賴項。我們不會深入探討節點包,因為它超出了本文的範圍,但您可以在本文中閱讀更多關於npm安裝包的位置的文章

build資料夾包含構建過程產生的JS和CSS檔案。您可以在ESNext語法JavaScript構建設定指南中深入瞭解構建過程。

專案:建造你的第一個古騰堡區塊

是時候弄髒我們的手了。本節將教你如何建立一個外掛,提供一個名為Affiliate Block的CTA區塊。

該區塊將由兩列組成,左側是影象,右側是文字段落。帶有可自定義連結的按鈕將放置在文字下方:

您將在本指南中學習構建的區塊型別

您將在本指南中學習構建的區塊型別

這只是一個簡單的示例,但它允許我們涵蓋古騰堡區塊開發的基礎知識。一旦你清楚地瞭解了基礎知識,你就可以在區塊編輯器手冊和任何其他可用的大量資源的幫助下繼續建立越來越複雜的古騰堡區塊。

Tips: 本教程中提供的示例程式碼也可以在Gist上找到,供您參考。

假設您在本地開發環境中執行了最新版本的WordPress,以下是您將從這裡學到的內容:

如何設定初學者區塊外掛

啟動命令列工具並導航到/wp-content/plugins資料夾:

Mac OS資料夾中的新終端

Mac OS資料夾中的新終端

現在,執行以下命令:

npx @wordpress/create-block

此命令生成用於在互動模式下注冊區塊的PHP、SCSS和JS檔案,使您可以輕鬆地為您的區塊新增必要的資料。對於我們的示例,我們將使用以下詳細資訊:

  • Block slug: my-affiliate-block
  • Internal namespace: my-affiliate-plugin
  • Block display title: Affiliate block
  • Short block description: An example block for Kinsta readers
  • Dashicon: money
  • Category name: design
  • Plugin author: your name
  • License: –
  • Link to the license text: –
  • Current plugin version: 0.1.0

安裝外掛和所有依賴項需要幾分鐘。該過程完成後,您將看到以下響應:

已安裝並註冊了Affiliate區塊以進行開發

已安裝並註冊了Affiliate區塊以進行開發

現在,從/wp-content/plugins資料夾執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cd my-affiliate-block
cd my-affiliate-block
cd my-affiliate-block

Tips: 如果您正在執行WordPress環境,則應首先啟動Docker Desktop,然後從外掛資料夾中執行wp-env start

然後,您可以從Web瀏覽器啟動http://localhost:8888/wp-login並使用Username:adminPassword:password登入到您的WordPress儀表盤。

從Visual Studio程式碼終端執行命令

從Visual Studio程式碼終端執行命令

最後,在您的外掛資料夾中(在我們的示例中為my-affiliate-block),您可以使用以下命令開始開發:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm start
npm start
npm start

現在開啟外掛螢幕以查詢並啟用Affiliate Block外掛:

Affiliate區塊外掛

Affiliate區塊外掛

建立一個新文章,開啟區塊插入器,然後向下滾動到設計Design類別。單擊以新增Affiliate區塊:

使用@wordpress/create-block構建的初學者區塊

使用@wordpress/create-block構建的初學者區塊

工作中的block.json

正如我們前面提到的,伺服器端區塊註冊發生在主.php檔案中。但是,我們不會在.php檔案中定義設定。相反,我們將使用block.json檔案。

因此,再次開啟block.json並仔細檢視預設設定:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"apiVersion": 2,
"name": "my-affiliate-plugin/my-affiliate-block",
"version": "0.1.0",
"title": "Affiliate Block",
"category": "design",
"icon": "money",
"description": "An example block for Kinsta readers",
"supports": {
"html": false
},
"textdomain": "my-affiliate-block",
"editorScript": "file:./build/index.js",
"editorStyle": "file:./build/index.css",
"style": "file:./build/style-index.css"
}
{ "apiVersion": 2, "name": "my-affiliate-plugin/my-affiliate-block", "version": "0.1.0", "title": "Affiliate Block", "category": "design", "icon": "money", "description": "An example block for Kinsta readers", "supports": { "html": false }, "textdomain": "my-affiliate-block", "editorScript": "file:./build/index.js", "editorStyle": "file:./build/index.css", "style": "file:./build/style-index.css" }
{
"apiVersion": 2,
"name": "my-affiliate-plugin/my-affiliate-block",
"version": "0.1.0",
"title": "Affiliate Block",
"category": "design",
"icon": "money",
"description": "An example block for Kinsta readers",
"supports": {
"html": false
},
"textdomain": "my-affiliate-block",
"editorScript": "file:./build/index.js",
"editorStyle": "file:./build/index.css",
"style": "file:./build/style-index.css"
}

指令碼和樣式

editorScripteditorStylestyle屬性提供前端和後端指令碼和樣式的相對路徑。

您不必手動註冊此處定義的指令碼和樣式,因為它們是由WordPress自動註冊和排隊的。為了證明這一點,啟動瀏覽器檢查器並開啟Network選項卡:

檢查Chrome DevTools中的資源

檢查Chrome DevTools中的資源

從上圖中可以看出,我們駐留在build資料夾中的index.js指令碼已定期排入佇列,而無需新增任何PHP程式碼

使用者介面標籤

titledescription屬性提供了在編輯器中識別區塊所需的標籤:

區塊側欄中的塊名稱和描述

區塊側欄中的區塊名稱和描述

關鍵詞

正如我們之前提到的,您可以使用propertiesattributes準確地配置您的區塊設定。例如,您可以新增一個或多個keywords來幫助使用者搜尋區塊:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{ "keywords": [ "wbolt", "affiliate", "money" ] }
{ "keywords": [ "wbolt", "affiliate", "money" ] }
{ "keywords": [ "wbolt", "affiliate", "money" ] }

如果您現在在快速插入器中輸入“wbolt”、“affiliate”或“money”,編輯器會建議您使用Affiliate區塊:

在快速插入器中使用關鍵字搜尋區塊

在快速插入器中使用關鍵字搜尋區塊

本土化

如果您想知道JSON檔案中字串的本地化是如何發生的,答案如下:

在JavaScript中,您可以使用@wordpress/blocks包中的now registerBlockTypeFromMetadata方法使用從block.json檔案載入的後設資料註冊區塊型別。所有本地化屬性都會自動包裝在_x(來自 @wordpress/i18n包)函式呼叫中,類似於它在PHP中的register_block_type_from_metadata工作方式。唯一的要求是在block.json檔案中設定textdomain屬性。

這裡我們使用registerBlockType函式而不是registerBlockTypeFromMetadata,因為後者自古騰堡10.7以來已被棄用,但機制是相同的。

使用內建元件:RichText元件

構成Gutenberg區塊的元素是React元件,您可以通過wp全域性變數訪問這些元件。例如,嘗試在瀏覽器的控制檯中輸入wp.editor。這將為您提供wp.editor模組中包含的元件的完整列表。

滾動列表並猜測其名稱所代表的元件。

同樣,您可以檢查wp.components模組中包含的元件列表:

WP編輯器元件

WP編輯器元件

Tips: 模組化程式設計是一種軟體設計技術,強調將程式的功能分離為獨立的、可互換的模組,這樣每個模組都包含執行所需功能的一個方面所需的一切(來源:維基百科)。

現在回到edit.js檔案並仔細檢視指令碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p {...useBlockProps()}>
{__('My First Block – hello from the editor!', 'my-first-block')}
</p>
);
}
import { __ } from '@wordpress/i18n'; import { useBlockProps } from '@wordpress/block-editor'; import './editor.scss'; export default function Edit() { return ( <p {...useBlockProps()}> {__('My First Block – hello from the editor!', 'my-first-block')} </p> ); }
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p {...useBlockProps()}>
{__('My First Block – hello from the editor!', 'my-first-block')}
</p>
);
}

此程式碼生成一個帶有簡單、不可編輯文字的靜態區塊。但是我們可以很容易地改變:

程式碼編輯器中的初學者區塊

程式碼編輯器中的初學者區塊

要使文字可編輯,您必須將當前<p>標記替換為使輸入內容可編輯的元件。為此,Gutenberg提供了內建的RichText元件

將內建元件新增到區塊中需要5個步驟:

  1. 從WordPress包中匯入所需的元件
  2. 在JSX程式碼中包含相應的元素
  3. 在block.json檔案中定義必要的屬性
  4. 定義事件處理程式
  5. 儲存資料

第 1 步:從WordPress包中匯入所需的元件

現在開啟edit.js檔案並更改以下import語句:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { useBlockProps } from '@wordpress/block-editor';
import { useBlockProps } from '@wordpress/block-editor';
import { useBlockProps } from '@wordpress/block-editor';

…到:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { useBlockProps, RichText } from '@wordpress/block-editor';

這樣,您就可以從 @wordpress/block-editor包中匯入useBlockProps函式和 RichText元件。

使用BlockProps

useBlockPropsReact鉤子標記了區塊的wrapper元素

使用API版本2時,您必須使用區塊函式edit中的新鉤子useBlockProps來標記區塊的wrapper元素。該鉤子將插入啟用區塊行為所需的屬性和事件處理程式。您希望傳遞給區塊元素的任何屬性都必須通過useBlockProps傳遞,並且返回的值必須分佈到元素上。

簡單地說,useBlockProps自動將屬性和類分配給wrapper元素(我們示例中的p元素):

由useBlockProps生成的元素和類

由useBlockProps生成的元素和類

如果useBlockProps從wrapper元素中刪除,您將擁有一個簡單的文字字串,無法訪問區塊功能和樣式:

沒有useBlockProps的同一個區塊

沒有useBlockProps的同一個區塊

正如我們稍後將解釋的,您還可以傳遞給useBlockProps屬性物件來自定義輸出。

富文字

RichText元件提供了一個contenteditable輸入,允許使用者編輯和格式化內容。

您可以在GitHub上的gutenberg/packages/block-editor/src/components/rich-text/README.md找到該元件。

第 2 步:在JSX程式碼中包含相應的元素

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
...
const blockProps = useBlockProps();
return (
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
/>
);
... const blockProps = useBlockProps(); return ( <RichText { ...blockProps } tagName="p" onChange={ onChangeContent } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ attributes.content } placeholder={ __( 'Write your text...' ) } /> );
...
const blockProps = useBlockProps();
return (
<RichText 
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
/>
);

讓我們逐行註釋程式碼:

  • tagName— 可編輯HTML元素的標籤名稱
  • onChange— 當元素內容改變時呼叫的函式
  • allowedFormats— 一組允許的格式。預設情況下,允許所有格式
  • value— 可編輯的HTML字串
  • placeholder— 當元素為空時顯示的佔位符文字

第 3 步:在block.json檔案中定義必要的屬性

屬性提供有關區塊儲存的資料的資訊,例如豐富的內容、背景顏色、URL等。

您可以在一個物件中以鍵/值對的形式設定任意數量的屬性attributes,其中鍵是屬性名稱,值是屬性定義。

現在開啟block.json檔案並新增以下屬性attributes

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
}
},
"attributes": { "content": { "type": "string", "source": "html", "selector": "p" } },
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
}
},

content屬性允許將使用者輸入的文字儲存在可編輯欄位中:

  • type表示屬性儲存的資料型別。除非您定義enum屬性,否則該型別是必需的。
  • source定義如何從文章內容中提取屬性值。在我們的示例中,它是HTML內容。請注意,如果您不提供源屬性,則資料將儲存在區塊分隔符中(閱讀更多)。
  • selector是HTML標記或任何其他選擇器,例如類名或id屬性。

我們將向Edit函式傳遞一個屬性物件。因此,返回到edit.js檔案並進行以下更改:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function Edit( { attributes, setAttributes } ) { ... }
export default function Edit( { attributes, setAttributes } ) { ... }
export default function Edit( { attributes, setAttributes } ) { ... }

第 4 步:定義事件處理程式

RichText元素有一個onChange屬性,當元素的內容改變時提供一個函式來呼叫。

讓我們定義該函式並檢視整個edit.js指令碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
return (
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
/>
);
}
import { __ } from '@wordpress/i18n'; import { useBlockProps, RichText } from '@wordpress/block-editor'; import './editor.scss'; export default function Edit( { attributes, setAttributes } ) { const blockProps = useBlockProps(); const onChangeContent = ( newContent ) => { setAttributes( { content: newContent } ) } return ( <RichText { ...blockProps } tagName="p" onChange={ onChangeContent } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ attributes.content } placeholder={ __( 'Write your text...' ) } /> ); }
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
return (
<RichText 
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
/>
);
}

現在儲存檔案並在終端視窗中執行npm run start。然後,返回您的WordPress儀表盤,建立一個新文章或頁面並新增您的Affiliate區塊:

區塊編輯器中RichText元件的輸出

區塊編輯器中RichText元件的輸出

新增一些文字並切換到程式碼檢視。這是您的程式碼應如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!-- wp:my-affiliate-plugin/my-affiliate-block -->
<p class="wp-block-my-affiliate-plugin-my-affiliate-block">This is my first editable Gutenberg block 🤓</p>
<!-- /wp:my-affiliate-plugin/my-affiliate-block -->
<!-- wp:my-affiliate-plugin/my-affiliate-block --> <p class="wp-block-my-affiliate-plugin-my-affiliate-block">This is my first editable Gutenberg block 🤓</p> <!-- /wp:my-affiliate-plugin/my-affiliate-block -->
<!-- wp:my-affiliate-plugin/my-affiliate-block -->
<p class="wp-block-my-affiliate-plugin-my-affiliate-block">This is my first editable Gutenberg block 🤓</p>
<!-- /wp:my-affiliate-plugin/my-affiliate-block -->

如果您現在儲存頁面並檢查前端結果,您可能會有點失望,因為您的更改不會影響站點。那是因為您必須修改save.js檔案以在儲存文章時將使用者輸入儲存在資料庫中。

第 5 步:儲存資料

現在開啟save.js檔案並更改指令碼如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ attributes.content }
/>
);
}
import { __ } from '@wordpress/i18n'; import { useBlockProps, RichText } from '@wordpress/block-editor'; export default function save( { attributes } ) { const blockProps = useBlockProps.save(); return ( <RichText.Content { ...blockProps } tagName="p" value={ attributes.content } /> ); }
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<RichText.Content 
{ ...blockProps } 
tagName="p" 
value={ attributes.content } 
/>
);
}

這就是我們在這裡所做的:

  • RichText從包中匯入元件block-editor
  • 通過一個物件引數向save函式傳遞幾個屬性(在這個例子中,我們只傳遞了attributes屬性
  • 返回元件的RichText內容

注:每當您更改儲存功能時,您必須刪除編輯器畫布中的任何區塊例項並再次包含它以檢視它是否正常工作。閱讀有關區塊驗證的更多資訊。

您可以在區塊編輯器手冊中閱讀有關該RichText元件的更多資訊,並在Github上找到完整的道具列表。

現在讓我們更進一步。在下一節中,您將學習如何將控制元件新增到區塊工具欄。

向區塊工具欄新增控制元件

區塊工具欄包含一組控制元件,允許使用者操作部分割槽塊內容。對於每個工具欄控制元件,您都會找到一個元件:

核心段落區塊工具欄

核心段落區塊工具欄

例如,您可以為區塊新增文字對齊控制元件。您需要做的就是從@wordpress/block-editor包中匯入兩個元件。

我們將執行與上一個示例相同的步驟:

  1. 從WordPress包中匯入所需的元件
  2. 在JSX程式碼中包含相應的元素
  3. block.json檔案中定義必要的屬性
  4. 定義事件處理程式
  5. 儲存資料

第 1 步:從@wordpress/block-editor匯入BlockControls和AlignmentControl元件

要將對齊控制元件新增到區塊工具欄,您需要兩個元件:

  • BlockControls呈現控制元件的動態工具欄(未記錄)。
  • AlignmentControl呈現一個下拉選單,顯示所選區塊的對齊選項(閱讀更多

開啟edit.js檔案,編輯import語句如下圖:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import {
useBlockProps,
RichText,
AlignmentControl,
BlockControls
} from '@wordpress/block-editor';
import { useBlockProps, RichText, AlignmentControl, BlockControls } from '@wordpress/block-editor';
import { 
useBlockProps, 
RichText, 
AlignmentControl, 
BlockControls 
} from '@wordpress/block-editor';

第 2 步:新增BlockControls和AlignmentControl元素

轉到Edit函式並插入與<RichText />相同級別的元素<BlockControls />。然後在<BlockControls />內新增和<AlignmentControl />

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
return (
<>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: attributes.align } }
/>
</>
);
}
export default function Edit( { attributes, setAttributes } ) { const blockProps = useBlockProps(); return ( <> <BlockControls> <AlignmentControl value={ attributes.align } onChange={ onChangeAlign } /> </BlockControls> <RichText { ...blockProps } tagName="p" onChange={ onChangeContent } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ attributes.content } placeholder={ __( 'Write your text...' ) } style={ { textAlign: attributes.align } } /> </> ); }
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
return (
<>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText 
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: attributes.align } }
/>
</>
);
}

在上面的程式碼中,<></>是宣告React片段的簡短語法,這是我們在React中返回多個元素的方式。

在這個例子中,AlignmentControl有兩個屬性:

我們還為RichText元素定義了額外的屬性(檢視完整的屬性列表和示例

第三步:在block.json中定義align屬性

現在轉到block.json檔案並新增align屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"align": {
"type": "string",
"default": "none"
}
"align": { "type": "string", "default": "none" }
"align": {
"type": "string",
"default": "none"
}

返回終端,使用^C停止當前程序並使用npm run start重新啟動指令碼。然後返回區塊編輯器,重新整理頁面並選擇區塊。您應該會看到帶有對齊控制元件的區塊工具欄:

對齊工具欄已成功新增

對齊工具欄已成功新增

現在,如果您嘗試使用新的對齊控制元件格式化區塊內容,您會發現沒有任何反應。那是因為我們還沒有定義事件處理程式。

第 4 步:定義事件處理程式

現在定義onChangeAlign

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
const onChangeAlign = ( newAlign ) => { setAttributes( { align: newAlign === undefined ? 'none' : newAlign, } ) }
const onChangeAlign = ( newAlign ) => {
setAttributes( { 
align: newAlign === undefined ? 'none' : newAlign, 
} )
}

如果newAlignundefined,那麼我們設定newAlignnone。否則,我們使用newAlign.

我們的edit.js指令碼應該是完整的(現在):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
return (
<>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: attributes.align } }
/>
</>
);
}
export default function Edit( { attributes, setAttributes } ) { const blockProps = useBlockProps(); const onChangeContent = ( newContent ) => { setAttributes( { content: newContent } ) } const onChangeAlign = ( newAlign ) => { setAttributes( { align: newAlign === undefined ? 'none' : newAlign, } ) } return ( <> <BlockControls> <AlignmentControl value={ attributes.align } onChange={ onChangeAlign } /> </BlockControls> <RichText { ...blockProps } tagName="p" onChange={ onChangeContent } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ attributes.content } placeholder={ __( 'Write your text...' ) } style={ { textAlign: attributes.align } } /> </> ); }
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( { 
align: newAlign === undefined ? 'none' : newAlign, 
} )
}
return (
<>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText 
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: attributes.align } }
/>
</>
);
}

現在您可以返回編輯器並對齊區塊內容。

我們需要修改save函式,將區塊的內容和屬性儲存在資料庫中。

第 5 步:儲存資料

開啟save.js,修改save函式如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ attributes.content }
style={ { textAlign: attributes.align } }
/>
);
}
export default function save( { attributes } ) { const blockProps = useBlockProps.save(); return ( <RichText.Content { ...blockProps } tagName="p" value={ attributes.content } style={ { textAlign: attributes.align } } /> ); }
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<RichText.Content 
{ ...blockProps } 
tagName="p" 
value={ attributes.content } 
style={ { textAlign: attributes.align } }
/>
);
}

最後,為了使程式碼更具可讀性,您可以使用解構賦值語法attribute物件中提取各個屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align } = attributes;
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ content }
style={ { textAlign: align } }
/>
);
}
export default function save( { attributes } ) { const blockProps = useBlockProps.save(); const { content, align } = attributes; return ( <RichText.Content { ...blockProps } tagName="p" value={ content } style={ { textAlign: align } } /> ); }
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align } = attributes;
return (
<RichText.Content 
{ ...blockProps } 
tagName="p" 
value={ content } 
style={ { textAlign: align } }
/>
);
}

儲存檔案,重新啟動程序並以程式碼編輯器模式返回編輯器。程式碼應如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!-- wp:my-affiliate-plugin/my-affiliate-block {"align":"right"} -->
<p class="wp-block-my-affiliate-plugin-my-affiliate-block" style="text-align:right">This is my first editable <strong><em>Gutenberg</em></strong> <em>block</em> 🤓</p>
<!-- /wp:my-affiliate-plugin/my-affiliate-block -->
<!-- wp:my-affiliate-plugin/my-affiliate-block {"align":"right"} --> <p class="wp-block-my-affiliate-plugin-my-affiliate-block" style="text-align:right">This is my first editable <strong><em>Gutenberg</em></strong> <em>block</em> 🤓</p> <!-- /wp:my-affiliate-plugin/my-affiliate-block -->
<!-- wp:my-affiliate-plugin/my-affiliate-block {"align":"right"} -->
<p class="wp-block-my-affiliate-plugin-my-affiliate-block" style="text-align:right">This is my first editable <strong><em>Gutenberg</em></strong> <em>block</em> 🤓</p>
<!-- /wp:my-affiliate-plugin/my-affiliate-block -->

右對齊文字

右對齊文字

就是這樣!您剛剛向區塊工具欄新增了對齊控制元件🤓

您可以在區塊編輯器手冊中閱讀有關區塊工具欄控制元件的更多資訊

自定義區塊設定側邊欄

您還可以將控制元件新增到區塊設定側邊欄(甚至為您的應用程式建立一個新的側邊欄)。

API為此提供了一個InspectorControls元件

區塊編輯器手冊解釋了如何使用設定邊欄

設定側邊欄用於顯示不常用的設定或需要更多螢幕空間的設定。設定側邊欄應僅用於塊級設定

如果您的設定僅影響區塊內的選定內容(例如:段落內選定文字的“粗體”設定):請勿將其放在設定側邊欄中。即使在HTML模式下編輯區塊時也會顯示設定側邊欄,因此它應該只包含區塊級設定。

再次:

  1. 從WordPress包中匯入所需的元件
  2. 在JSX程式碼中包含相應的元素
  3. 在block.json檔案中定義必要的屬性
  4. 定義事件處理程式
  5. 儲存資料

步驟 1. 從@wordpress/block-editor匯入InspectorControls和PanelColorSettings元件

您可以新增多個控制元件以允許使用者自定義區塊的特定方面。例如,您可以提供一個顏色控制面板。為此,您需要從block-editor模組中匯入InspectorControlsPanelColorSettings元件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import {
useBlockProps,
RichText,
AlignmentControl,
BlockControls,
InspectorControls,
PanelColorSettings
} from '@wordpress/block-editor';
import { useBlockProps, RichText, AlignmentControl, BlockControls, InspectorControls, PanelColorSettings } from '@wordpress/block-editor';
import { 
useBlockProps, 
RichText, 
AlignmentControl, 
BlockControls,
InspectorControls,
PanelColorSettings
} from '@wordpress/block-editor';

第 2 步:在JSX程式碼中包含相應的元素
現在您可以將相應的元素新增到Edit函式返回的JSX中:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
return (
<>
<InspectorControls>
<PanelColorSettings
title={ __( 'Color settings', 'my-affiliate-block' ) }
initialOpen={ false }
colorSettings={ [
{
value: textColor,
onChange: onChangeTextColor,
label: __( 'Text color', 'my-affiliate-block' ),
},
{
value: backgroundColor,
onChange: onChangeBackgroundColor,
label: __( 'Background color', 'my-affiliate-block' ),
}
] }
/>
</InspectorControls>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...', 'my-affiliate-block' ) }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
</>
);
}
export default function Edit( { attributes, setAttributes } ) { const blockProps = useBlockProps(); const onChangeContent = ( newContent ) => { setAttributes( { content: newContent } ) } const onChangeAlign = ( newAlign ) => { setAttributes( { align: newAlign === undefined ? 'none' : newAlign, } ) } return ( <> <InspectorControls> <PanelColorSettings title={ __( 'Color settings', 'my-affiliate-block' ) } initialOpen={ false } colorSettings={ [ { value: textColor, onChange: onChangeTextColor, label: __( 'Text color', 'my-affiliate-block' ), }, { value: backgroundColor, onChange: onChangeBackgroundColor, label: __( 'Background color', 'my-affiliate-block' ), } ] } /> </InspectorControls> <BlockControls> <AlignmentControl value={ attributes.align } onChange={ onChangeAlign } /> </BlockControls> <RichText { ...blockProps } tagName="p" onChange={ onChangeContent } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ attributes.content } placeholder={ __( 'Write your text...', 'my-affiliate-block' ) } style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } } /> </> ); }
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( { 
align: newAlign === undefined ? 'none' : newAlign, 
} )
}
return (
<>
<InspectorControls>
<PanelColorSettings 
title={ __( 'Color settings', 'my-affiliate-block' ) }
initialOpen={ false }
colorSettings={ [
{
value: textColor,
onChange: onChangeTextColor,
label: __( 'Text color', 'my-affiliate-block' ),
},
{
value: backgroundColor,
onChange: onChangeBackgroundColor,
label: __( 'Background color', 'my-affiliate-block' ),
}
] }
/>
</InspectorControls>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText 
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...', 'my-affiliate-block' ) }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
</>
);
}

請注意,我們還更新了RichText元素的style屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ content }
placeholder={ __( 'Write your text...', 'my-affiliate-block' ) }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
<RichText { ...blockProps } tagName="p" onChange={ onChangeContent } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ content } placeholder={ __( 'Write your text...', 'my-affiliate-block' ) } style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } } />
<RichText 
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ content }
placeholder={ __( 'Write your text...', 'my-affiliate-block' ) }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>

第 3 步:在block.json中定義必要的屬性

現在在block.json檔案中定義backgroundColortextColor屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"backgroundColor": {
"type": "string"
},
"textColor": {
"type": "string"
}
},
"attributes": { "content": { "type": "string", "source": "html", "selector": "p" }, "align": { "type": "string", "default": "none" }, "backgroundColor": { "type": "string" }, "textColor": { "type": "string" } },
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"backgroundColor": {
"type": "string"
},	 
"textColor": {
"type": "string"
}
},

第 4 步:定義事件處理程式

現在您需要定義backgroundColortextColor兩個函式來更新使用者輸入:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const onChangeBackgroundColor = ( newBackgroundColor ) => {
setAttributes( { backgroundColor: newBackgroundColor } )
}
const onChangeTextColor = ( newTextColor ) => {
setAttributes( { textColor: newTextColor } )
}
const onChangeBackgroundColor = ( newBackgroundColor ) => { setAttributes( { backgroundColor: newBackgroundColor } ) } const onChangeTextColor = ( newTextColor ) => { setAttributes( { textColor: newTextColor } ) }
const onChangeBackgroundColor = ( newBackgroundColor ) => {
setAttributes( { backgroundColor: newBackgroundColor } )
}
const onChangeTextColor = ( newTextColor ) => {
setAttributes( { textColor: newTextColor } )
}

第 5 步:儲存資料

最後一步:開啟save.js檔案並按如下方式更改指令碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align, backgroundColor, textColor } = attributes;
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ content }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
);
}
export default function save( { attributes } ) { const blockProps = useBlockProps.save(); const { content, align, backgroundColor, textColor } = attributes; return ( <RichText.Content { ...blockProps } tagName="p" value={ content } style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } } /> ); }
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align, backgroundColor, textColor } = attributes;
return (
<RichText.Content 
{ ...blockProps } 
tagName="p" 
value={ content } 
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
);
}

現在停止程序 (^C) 並再次執行npm run start。重新整理頁面,刪除任何區塊例項並將其再次新增到您的文章中:

帶有顏色設定面板的自定義區塊

帶有顏色設定面板的自定義區塊

進行更改,儲存文章,然後在前端檢視。您在區塊編輯器中所做的更改應反映在前端站點上。

在本節中,您將向區塊型別新增新元件:

  • ExternalLink允許使用者將可自定義連結新增到Affiliate區塊的元件
  • 幾個側邊欄控制元件允許使用者自定義連結設定

步驟 1. 從@wordpress/components匯入元件

現在需要從@wordpress/components匯入幾個元件。開啟你的edit.js檔案並新增以下import語句:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import {
TextControl,
PanelBody,
PanelRow,
ToggleControl,
ExternalLink
} from '@wordpress/components';
import { TextControl, PanelBody, PanelRow, ToggleControl, ExternalLink } from '@wordpress/components';
import {
TextControl,
PanelBody,
PanelRow,
ToggleControl,
ExternalLink
} from '@wordpress/components';
  • PanelBody將可摺疊容器新增到設定側邊欄。
  • PaneRow為側邊欄控制元件生成一個通用容器。
  • TextControl提供文字輸入控制元件。
  • ToggleControl提供一個切換,使使用者能夠啟用/禁用特定選項
  • ExternalLink是一個新增外部連結的簡單元件。

步驟 2. 在JSX程式碼中包含相應的元素

您將首先在div容器中新增ExternalLinkRichText相同級別的元素:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<div { ...blockProps }>
<RichText
...
/>
<ExternalLink
href={ affiliateLink }
className="affiliate-button"
rel={ hasLinkNofollow ? "nofollow" : "" }
>
{ linkLabel }
</ExternalLink>
</div>
<div { ...blockProps }> <RichText ... /> <ExternalLink href={ affiliateLink } className="affiliate-button" rel={ hasLinkNofollow ? "nofollow" : "" } > { linkLabel } </ExternalLink> </div>
<div { ...blockProps }>
<RichText 
...
/>
<ExternalLink 
href={ affiliateLink }
className="affiliate-button"
rel={ hasLinkNofollow ? "nofollow" : "" }
>
{ linkLabel }
</ExternalLink>
</div>

ExternalLink元件沒有記錄,因此我們參考了元件本身來獲取可用屬性的列表。這裡我們使用hrefclassNamerel屬性。

預設情況下,rel屬性值設定為noopener noreferrer。當切換控制元件為on時,我們的程式碼將把nofollow新增到生成的標記的rel屬性中。

現在您可以將連結設定新增到區塊側邊欄。

首先,在InspectorControls中新增一個與PanelColorSettings處於同一級別的PanelBody元素:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<InspectorControls>
<PanelColorSettings
...
/>
<PanelBody
title={ __( 'Link Settings', 'my-affiliate-block' )}
initialOpen={true}
>
...
</PanelBody>
</InspectorControls>
<InspectorControls> <PanelColorSettings ... /> <PanelBody title={ __( 'Link Settings', 'my-affiliate-block' )} initialOpen={true} > ... </PanelBody> </InspectorControls>
<InspectorControls>
<PanelColorSettings 
...
/>
<PanelBody 
title={ __( 'Link Settings', 'my-affiliate-block' )}
initialOpen={true}
>
...
</PanelBody>
</InspectorControls>

這是我們正在做的事情:

  1. title屬性提供面板標題。
  2. initialOpen設定面板最初是否開啟。

接下來,我們將在PanelBody內部新增兩個元素PanelRow,並在每個PanelRow內部新增一個TextControl元素:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<PanelBody
title={ __( 'Link Settings', 'my-affiliate-block' )}
initialOpen={true}
>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Affiliate link', 'my-affiliate-block' )}
value={ affiliateLink }
onChange={ onChangeAffiliateLink }
help={ __( 'Add your affiliate link', 'my-affiliate-block' )}
/>
</fieldset>
</PanelRow>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Link label', 'my-affiliate-block' )}
value={ linkLabel }
onChange={ onChangeLinkLabel }
help={ __( 'Add link label', 'my-affiliate-block' )}
/>
</fieldset>
</PanelRow>
</PanelBody>
<PanelBody title={ __( 'Link Settings', 'my-affiliate-block' )} initialOpen={true} > <PanelRow> <fieldset> <TextControl label={__( 'Affiliate link', 'my-affiliate-block' )} value={ affiliateLink } onChange={ onChangeAffiliateLink } help={ __( 'Add your affiliate link', 'my-affiliate-block' )} /> </fieldset> </PanelRow> <PanelRow> <fieldset> <TextControl label={__( 'Link label', 'my-affiliate-block' )} value={ linkLabel } onChange={ onChangeLinkLabel } help={ __( 'Add link label', 'my-affiliate-block' )} /> </fieldset> </PanelRow> </PanelBody>
<PanelBody 
title={ __( 'Link Settings', 'my-affiliate-block' )}
initialOpen={true}
>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Affiliate link', 'my-affiliate-block' )}
value={ affiliateLink }
onChange={ onChangeAffiliateLink }
help={ __( 'Add your affiliate link', 'my-affiliate-block' )}
/>
</fieldset>
</PanelRow>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Link label', 'my-affiliate-block' )}
value={ linkLabel }
onChange={ onChangeLinkLabel }
help={ __( 'Add link label', 'my-affiliate-block' )}
/>
</fieldset>
</PanelRow>
</PanelBody>

上面的程式碼現在看起來應該很簡單了。這兩個文字控制元件允許使用者設定連結標籤和URL。

我們還將新增一個附加選項來開啟/關閉特定選項,例如是否包含屬性:

我們還將新增一個帶有ToggleControl的額外PanelRow,以開啟/關閉特定選項,例如是否包含屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<PanelRow>
<fieldset>
<ToggleControl
label="Add rel = nofollow"
help={
hasLinkNofollow
? 'Has rel nofollow.'
: 'No rel nofollow.'
}
checked={ hasLinkNofollow }
onChange={ toggleNofollow }
/>
</fieldset>
</PanelRow>
<PanelRow> <fieldset> <ToggleControl label="Add rel = nofollow" help={ hasLinkNofollow ? 'Has rel nofollow.' : 'No rel nofollow.' } checked={ hasLinkNofollow } onChange={ toggleNofollow } /> </fieldset> </PanelRow>
<PanelRow>
<fieldset>
<ToggleControl
label="Add rel = nofollow"
help={
hasLinkNofollow
? 'Has rel nofollow.'
: 'No rel nofollow.'
}
checked={ hasLinkNofollow }
onChange={ toggleNofollow }
/>
</fieldset>
</PanelRow>

第 3 步:在block.json中定義必要的屬性

現在在block.json檔案中定義affiliateLinklinkLabelhasLinkNofollow屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"affiliateLink": {
"type": "string",
"default": ""
},
"linkLabel": {
"type": "string",
"default": "Check it out!"
},
"hasLinkNofollow": {
"type": "boolean",
"default": false
}
"affiliateLink": { "type": "string", "default": "" }, "linkLabel": { "type": "string", "default": "Check it out!" }, "hasLinkNofollow": { "type": "boolean", "default": false }
"affiliateLink": {
"type": "string",
"default": ""
},
"linkLabel": {
"type": "string",
"default": "Check it out!"
},
"hasLinkNofollow": {
"type": "boolean",
"default": false
}

這裡沒有什麼要補充的了!讓我們繼續定義事件處理函式

第 4 步:定義事件處理程式

回到edit.js檔案並新增以下函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const onChangeAffiliateLink = ( newAffiliateLink ) => {
setAttributes( { affiliateLink: newAffiliateLink === undefined ? '' : newAffiliateLink } )
}
const onChangeLinkLabel = ( newLinkLabel ) => {
setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}
const toggleNofollow = () => {
setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}
const onChangeAffiliateLink = ( newAffiliateLink ) => { setAttributes( { affiliateLink: newAffiliateLink === undefined ? '' : newAffiliateLink } ) } const onChangeLinkLabel = ( newLinkLabel ) => { setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } ) } const toggleNofollow = () => { setAttributes( { hasLinkNofollow: ! hasLinkNofollow } ) }
const onChangeAffiliateLink = ( newAffiliateLink ) => {
setAttributes( { affiliateLink: newAffiliateLink === undefined ? '' : newAffiliateLink } )
}
const onChangeLinkLabel = ( newLinkLabel ) => {
setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}
const toggleNofollow = () => {
setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}

這些函式更新使用者輸入的相應屬性值。

第 5 步:儲存資料

最後,我們必須更新save.js中的save函式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function save( { attributes } ) {
const { align, content, backgroundColor, textColor, affiliateLink, linkLabel, hasLinkNofollow } = attributes;
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<RichText.Content
tagName="p"
value={ content }
style={ { backgroundColor: backgroundColor, color: textColor } }
/>
<p>
<a
href={ affiliateLink }
className="affiliate-button"
rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
>
{ linkLabel }
</a>
</p>
</div>
);
}
export default function save( { attributes } ) { const { align, content, backgroundColor, textColor, affiliateLink, linkLabel, hasLinkNofollow } = attributes; const blockProps = useBlockProps.save(); return ( <div { ...blockProps }> <RichText.Content tagName="p" value={ content } style={ { backgroundColor: backgroundColor, color: textColor } } /> <p> <a href={ affiliateLink } className="affiliate-button" rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" } > { linkLabel } </a> </p> </div> ); }
export default function save( { attributes } ) {
const { align, content, backgroundColor, textColor, affiliateLink, linkLabel, hasLinkNofollow } = attributes;
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<RichText.Content 
tagName="p" 
value={ content } 
style={ { backgroundColor: backgroundColor, color: textColor } }
/>
<p>
<a 
href={ affiliateLink }
className="affiliate-button"
rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
>
{ linkLabel }
</a>
</p>
</div>
);
}

請注意,這裡我們使用了常規a元素而不是ExternalLink

Affiliate區塊連結設定

Affiliate區塊連結設定

現在儲存資料並重新啟動您的環境。

新增多個區塊樣式

在上一節中,您學習瞭如何新增允許使用者對齊使用者輸入的區塊工具欄控制元件。我們可以向區塊工具欄新增更多樣式控制元件,但我們也可以提供一組預定義的區塊樣式,使用者只需單擊即可從中選擇。

為此,我們將使用Block API的一個有用功能:Block Styles

您需要做的就是定義block.json styles屬性並在樣式表中宣告相應的樣式。

例如,您可以新增以下樣式陣列:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{
"name": "border",
"label": "Border"
}
],
"styles": [ { "name": "default", "label": "Default", "isDefault": true }, { "name": "border", "label": "Border" } ],
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{
"name": "border",
"label": "Border"
}
],

有了這個,您剛剛新增了一個預設樣式和一個名為border. 現在回到區塊編輯器:

兩種預定義的區塊樣式

兩種預定義的區塊樣式

通過單擊區塊切換器,然後在區塊設定側邊欄中查詢樣式面板,使用者可以使用樣式。

選擇一種樣式並檢查應用於p元素的類。右鍵單擊區塊並檢查。新增了一個新類,其名稱結構如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
is-style-{style-name}
is-style-{style-name}
is-style-{style-name}

如果您選中了“Border”樣式,則會將一個is-style-border類新增到p元素中。如果您選中“Default”樣式,則會新增一個is-style-default類。

現在您只需要宣告CSS屬性。開啟editor.scss檔案並將當前樣式替換為以下內容:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.wp-block-my-affiliate-plugin-my-affiliate-block {
padding: 2px;
&.is-style-default{
border: 0;
}
&.is-style-border{
border: 1px solid #000;
}
}
.wp-block-my-affiliate-plugin-my-affiliate-block { padding: 2px; &.is-style-default{ border: 0; } &.is-style-border{ border: 1px solid #000; } }
.wp-block-my-affiliate-plugin-my-affiliate-block {
padding: 2px;
&.is-style-default{
border: 0;
}
&.is-style-border{
border: 1px solid #000;
}
}

現在你可以對style.scss做同樣的事情:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.wp-block-my-affiliate-plugin-my-affiliate-block {
&.is-style-default{
border: 0;
}
&.is-style-border{
border: 1px solid #000;
}
}
.wp-block-my-affiliate-plugin-my-affiliate-block { &.is-style-default{ border: 0; } &.is-style-border{ border: 1px solid #000; } }
.wp-block-my-affiliate-plugin-my-affiliate-block {
&.is-style-default{
border: 0;
}
&.is-style-border{
border: 1px solid #000;
}
}

停止程序 (^C) 並再次執行npm run start

就是這樣!重新整理頁面,享受新的區塊樣式:

Affiliate區塊樣式

Affiliate區塊樣式

使用InnerBlocks元件巢狀Gutenberg區塊

雖然功能齊全,但我們的Affiliate區塊仍然不是很吸引人。為了讓觀眾更感興趣,我們可以新增一張圖片。

這可能會給我們的區塊增加一層複雜性,但幸運的是,您不需要重新發明輪子,因為Gutenberg提供了一個特定的元件,您可以使用它來建立巢狀區塊的結構。

InnerBlocks元件定義如下

InnerBlocks匯出一對可用於區塊實現以啟用巢狀區塊內容的元件。

首先,您需要在src資料夾中建立一個新的.js檔案。在我們的示例中,我們將此檔案稱為container.js

現在您需要將新資源匯入index.js檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import './container';
import './container';
import './container';

回到container.js並匯入必要的元件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
useBlockProps,
InnerBlocks
} from "@wordpress/block-editor";
import { registerBlockType } from "@wordpress/blocks"; import { __ } from "@wordpress/i18n"; import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
useBlockProps, 
InnerBlocks 
} from "@wordpress/block-editor";

下一步是定義一個模板,提供將放置區塊的結構。在以下示例中,我們定義了一個模板,該模板由兩列組成,其中包含一個核心Image區塊和我們的自定義Affiliate區塊:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [ [ 'core/column', { templateLock: 'all' }, [ [ 'core/image' ], ] ], [ 'core/column', { templateLock: 'all' }, [ [ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ], ] ], ] ] ];
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];

模板的結構是一個blockTypes 陣列(區塊名稱和可選屬性)。

在上面的程式碼中,我們使用了幾個屬性來配置Columns和Column區塊。具體來說,templateLock: 'all'屬性鎖定Column區塊,以便使用者不會新增、重新排序或刪除現有區塊。templateLock可以採用以下值之一:

  • allInnerBlocks已鎖定,不能新增、重新排序或刪除任何區塊。
  • insert— 區塊只能重新排序或刪除。
  • false— 模板未鎖定。

然後將模板分配給InnerBlocks元素:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
/>
<InnerBlocks template={ TEMPLATE } templateLock="all" />
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
/>

為了防止出現任何相容性問題,我們還為InnerBlocks元件新增了一個templateLock屬性(另請參閱issue #17262和pull #26128)。

這是我們最終的container.js檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];
registerBlockType('my-affiliate-plugin/my-affiliate-container-block', {
title: __( 'Container', 'my-affiliate-block' ),
category: 'design',
edit( { className } ) {
return(
<div className={ className }>
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
/>
</div>
)
},
save() {
const blockProps = useBlockProps.save();
return(
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
)
},
});
import { registerBlockType } from "@wordpress/blocks"; import { __ } from "@wordpress/i18n"; import { useBlockProps, InnerBlocks } from "@wordpress/block-editor"; const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [ [ 'core/column', { templateLock: 'all' }, [ [ 'core/image' ], ] ], [ 'core/column', { templateLock: 'all' }, [ [ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ], ] ], ] ] ]; registerBlockType('my-affiliate-plugin/my-affiliate-container-block', { title: __( 'Container', 'my-affiliate-block' ), category: 'design', edit( { className } ) { return( <div className={ className }> <InnerBlocks template={ TEMPLATE } templateLock="all" /> </div> ) }, save() { const blockProps = useBlockProps.save(); return( <div { ...blockProps }> <InnerBlocks.Content /> </div> ) }, });
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];
registerBlockType('my-affiliate-plugin/my-affiliate-container-block', {
title: __( 'Container', 'my-affiliate-block' ),
category: 'design',
edit( { className } ) {
return(
<div className={ className }>
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
/>
</div>
)
},
save() {
const blockProps = useBlockProps.save();
return(
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
)
},
});

編輯器中的巢狀Affiliate區塊

編輯器中的巢狀Affiliate區塊

其他改進

我們的區塊功能齊全,但我們可以通過一些小改動對其進行一些改進。

我們將backgroundColor屬性分配給RichText元件生成的段落。但是,我們可能更喜歡將背景顏色分配給容器div

所以,修改edit.js檔案和save.js的 div如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<div
{ ...blockProps }
style={ { backgroundColor: backgroundColor } }
>
...
</div>
<div { ...blockProps } style={ { backgroundColor: backgroundColor } } > ... </div>
<div 
{ ...blockProps }
style={ { backgroundColor: backgroundColor } }
>
...
</div>

這將允許使用者更改整個區塊的背景。

另一方面,更相關的變化涉及useBlockProps方法。在原始程式碼中,我們定義常量blockProps如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const blockProps = useBlockProps();
const blockProps = useBlockProps();
const blockProps = useBlockProps();

但是我們可以使用useBlockProps更有效的傳遞一組屬性。例如,我們可以從classnames模組匯入classnames並相應地設定wrapper類名稱。

在以下示例中,我們根據align屬性的值分配一個類名 ( edit.js ):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import classnames from 'classnames';
...
export default function Edit( { attributes, setAttributes } ) {
...
const blockProps = useBlockProps( {
className: classnames( {
[ `has-text-align-${ align }` ]: align,
} )
} );
...
}
import classnames from 'classnames'; ... export default function Edit( { attributes, setAttributes } ) { ... const blockProps = useBlockProps( { className: classnames( { [ `has-text-align-${ align }` ]: align, } ) } ); ... }
import classnames from 'classnames';
...
export default function Edit( { attributes, setAttributes } ) {
...
const blockProps = useBlockProps( {
className: classnames( {
[ `has-text-align-${ align }` ]: align,
} )
} );
...
}

我們將在save.js檔案中進行相同的更改:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import classnames from 'classnames';
...
export default function save( { attributes } ) {
...
const blockProps = useBlockProps.save({
className: classnames( {
[ `has-text-align-${ align }` ]: align,
} )
});
...
}
import classnames from 'classnames'; ... export default function save( { attributes } ) { ... const blockProps = useBlockProps.save({ className: classnames( { [ `has-text-align-${ align }` ]: align, } ) }); ... }
import classnames from 'classnames';
...
export default function save( { attributes } ) {
...
const blockProps = useBlockProps.save({
className: classnames( {
[ `has-text-align-${ align }` ]: align,
} )
});
...
}

這是一個wrap!您現在可以為生產執行構建

小結

我們到了,在這個令人難以置信的旅程的盡頭!我們從開發環境的配置開始,最終建立了一個完整的區塊型別。

正如我們在介紹中提到的,Node.js、Webpack、Babel和React的紮實知識對於建立高階Gutenberg區塊並將自己定位為專業的Gutenberg開發人員至關重要。

但是,您無需具備React經驗即可開始享受區塊開發的樂趣。區塊開發可以為您提供動力和目標,讓您在古騰堡區塊背後的技術中獲得越來越廣泛的技能。

因此,本指南遠未完成。它只是對各種主題的介紹,可幫助您開始構建您的第一個古騰堡區塊。

因此,我們建議您通過仔細閱讀線上文件和指南來加深您的知識。在可用的眾多資源中,我們推薦以下內容:

如果您剛開始WordPress開發,您可能想了解前端開發的基本概念。以下是可以幫助您入門的資源的快速列表:

請記住,本指南示例的完整程式碼可在Gist上找到

評論留言