如何在古騰堡編輯器中為文章新增Meta框和自定義欄位

如何在古騰堡編輯器中為文章新增Meta框和自定義欄位

自定義欄位提供了一種為網站內容分配額外資訊的方法。這些資訊通常被稱為後設資料

後設資料是關於資訊的資訊。就WordPress而言,它是與帖子、使用者、評論和術語相關的資訊。

鑑於WordPress中後設資料的多對一關係,你的選擇是相當無限的。你可以有你想要的許多元選項,而且你可以在其中儲存幾乎任何東西。

Plugin Handbook

下面是一些你可以使用自定義欄位附加到文章的後設資料的例子:

  • 地方或房地產的地理座標
  • 事件的日期
  • 書的國際標準書號或作者
  • 文章作者當天的心情

或者更多其他資訊。

開箱即用,WordPress並沒有提供一個簡單的方法來新增和管理自定義欄位。在經典編輯器中,自定義欄位顯示在頁面底部的一個框中,位於文章編輯器的下面。

經典編輯器中的自定義欄位

經典編輯器中的自定義欄位。

在Gutenberg中,自定義欄位預設是禁用的,但你可以通過選擇文章設定中的相應專案來顯示它們。

將自定義欄位面板新增到區塊編輯器中

將自定義欄位面板新增到區塊編輯器中。

不幸的是,如果不使用外掛或不動手寫程式碼,就沒有辦法在前臺顯示後設資料。

如果你是一個使用者,你會發現有幾個優秀的外掛在為你做這項工作。但是,如果你是一個開發者,想從WordPress的自定義欄位中得到更多的東西,把它們無縫地整合到塊編輯器中,並使用自定義的Gutenberg塊在WordPress網站的前端顯示它們,那麼你就來對地方了。

因此,如果你想知道對於WordPress開發者來說,在Gutenberg經典編輯器中使用WordPress自定義欄位的最佳方式是什麼,快速的答案是 “建立一個既適用於經典編輯器又適用於Gutenberg的外掛”。

但不要太擔心。如果建立一個外掛來管理兩個編輯器中的自定義欄位可能有點棘手,我們會盡量使這個過程簡單明瞭。一旦你理解了我們將在本文中討論的概念,你將獲得在Gutenberg中管理自定義元欄位和建立各種網站所需的技能。

Info

本文假設你熟悉Node.js & npmReactJavaScript等技術。還需要有WordPress開發的基本知識。

如果你是Gutenberg區塊開發的新手,在開始閱讀本文之前,請務必檢視我們之前的指南:

注意:在做任何事情之前,確保你的電腦上有最新版本的Node.js

說了這麼多,下面是我們的詳細介紹:

  1. 用官方的create-block工具建立一個區塊外掛
  2. 在經典編輯器中新增後設資料框
  3. 在古騰堡區塊編輯器中新增自定義元欄位(三個選項)
  4. 進一步閱讀

用官方的create-block工具建立一個區塊外掛

第一步是建立一個新的外掛,包含註冊一個新的區塊型別所需的所有檔案和依賴性。塊外掛將允許你輕鬆地建立一個自定義塊型別,用於管理和顯示自定義後設資料。

為了建立一個新的區塊型別,我們將使用官方的create-block工具。關於如何使用create-block工具的詳細介紹,請檢視我們之前關於Gutenberg區塊開發的文章

開啟你的命令列工具,導航到你的WordPress開發網站的外掛目錄,執行以下命令:

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

當出現提示時,新增以下細節:

  • The template variant to use for this block: dynamic
  • The block slug used for identification (also the output folder name): metadata-block
  • The internal namespace for the block name (something unique for your products): meta-fields
  • The display title for your block: Meta Fields
  • The short description for your block (optional): Block description
  • The dashicon to make it easier to identify your block (optional): book
  • The category name to help users browse and discover your block: widgets
  • Do you want to customize the WordPress plugin? Yes/No

讓我們花點時間回顧一下這些細節,並嘗試瞭解它們的使用情況。

  • 用於識別的區塊slug定義了該外掛的資料夾名稱文字域
  • 區塊名稱的內部名稱空間定義了整個外掛程式碼中使用的區塊內部名稱空間函式字首
  • 區塊的顯示標題定義了外掛的名稱和編輯器介面中使用的區塊名稱

設定可能需要幾分鐘的時間。當這個過程完成後,你會得到一個可用命令的列表。

區塊外掛成功安裝

區塊外掛成功安裝。

在進入下一節之前,在你的命令列工具中,導航到你的外掛的資料夾並執行以下命令:

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

Important

確保每次啟動Gutenberg開發環境時都要執行 npm start 命令。

當你執行 npm start 時,一個觀察器將在終端執行,並在任何變化後重建JS和CSS檔案(閱讀更多)。

你已經準備好構建你的程式碼了。下一步是編輯外掛的主要PHP檔案,為經典編輯器建立一個元框。

因此,在進入下一節之前,請安裝並啟用經典編輯器外掛

然後,開啟外掛介面,啟用新的Meta Fields外掛。

啟用外掛

啟用外掛。

在經典編輯器中新增一個元框

經典編輯器的上下文中,元框是一個容納表單元素的容器,用於輸入特定的資訊,如文章作者、標籤、類別等。

除了內建的元框,外掛開發者可以新增任何數量的自定義元框,以包括HTML表單元素(或任何HTML內容),外掛使用者可以在其中輸入外掛的特定資料。

WordPress的API提供了有用的功能,可以輕鬆地註冊自定義元框,包括你的外掛工作所需的所有HTML元素。

要開始的話,把下面的程式碼附加到你剛剛建立的外掛的PHP檔案中:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// register meta box
function meta_fields_add_meta_box(){
add_meta_box(
'meta_fields_meta_box',
__( 'Book details' ),
'meta_fields_build_meta_box_callback',
'post',
'side',
'default'
);
}
// build meta box
function meta_fields_build_meta_box_callback( $post ){
wp_nonce_field( 'meta_fields_save_meta_box_data', 'meta_fields_meta_box_nonce' );
$title = get_post_meta( $post->ID, '_meta_fields_book_title', true );
$author = get_post_meta( $post->ID, '_meta_fields_book_author', true );
?>
<div class="inside">
<p><strong>Title</strong></p>
<p><input type="text" id="meta_fields_book_title" name="meta_fields_book_title" value="<?php echo esc_attr( $title ); ?>" /></p>
<p><strong>Author</strong></p>
<p><input type="text" id="meta_fields_book_author" name="meta_fields_book_author" value="<?php echo esc_attr( $author ); ?>" /></p>
</div>
<?php
}
add_action( 'add_meta_boxes', 'meta_fields_add_meta_box' );
// register meta box function meta_fields_add_meta_box(){ add_meta_box( 'meta_fields_meta_box', __( 'Book details' ), 'meta_fields_build_meta_box_callback', 'post', 'side', 'default' ); } // build meta box function meta_fields_build_meta_box_callback( $post ){ wp_nonce_field( 'meta_fields_save_meta_box_data', 'meta_fields_meta_box_nonce' ); $title = get_post_meta( $post->ID, '_meta_fields_book_title', true ); $author = get_post_meta( $post->ID, '_meta_fields_book_author', true ); ?> <div class="inside"> <p><strong>Title</strong></p> <p><input type="text" id="meta_fields_book_title" name="meta_fields_book_title" value="<?php echo esc_attr( $title ); ?>" /></p> <p><strong>Author</strong></p> <p><input type="text" id="meta_fields_book_author" name="meta_fields_book_author" value="<?php echo esc_attr( $author ); ?>" /></p> </div> <?php } add_action( 'add_meta_boxes', 'meta_fields_add_meta_box' );
// register meta box
function meta_fields_add_meta_box(){
add_meta_box(
'meta_fields_meta_box', 
__( 'Book details' ), 
'meta_fields_build_meta_box_callback', 
'post',
'side',
'default'
);
}
// build meta box
function meta_fields_build_meta_box_callback( $post ){
wp_nonce_field( 'meta_fields_save_meta_box_data', 'meta_fields_meta_box_nonce' );
$title = get_post_meta( $post->ID, '_meta_fields_book_title', true );
$author = get_post_meta( $post->ID, '_meta_fields_book_author', true );
?>
<div class="inside">
<p><strong>Title</strong></p>
<p><input type="text" id="meta_fields_book_title" name="meta_fields_book_title" value="<?php echo esc_attr( $title ); ?>" /></p>	
<p><strong>Author</strong></p>
<p><input type="text" id="meta_fields_book_author" name="meta_fields_book_author" value="<?php echo esc_attr( $author ); ?>" /></p>
</div>
<?php
}
add_action( 'add_meta_boxes', 'meta_fields_add_meta_box' );

add_meta_box 函式註冊了一個新的後設資料框,而回撥函式構建了要注入後設資料框的HTML。我們不會深入研究這個話題,因為它超出了我們文章的範圍,但你會在這裡這裡這裡找到你需要的所有細節。

下一步是建立一個函式,在save_post 鉤子被觸發的時候儲存帖子作者輸入的資料(見開發者資源):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// save metadata
function meta_fields_save_meta_box_data( $post_id ) {
if ( ! isset( $_POST['meta_fields_meta_box_nonce'] ) )
return;
if ( ! wp_verify_nonce( $_POST['meta_fields_meta_box_nonce'], 'meta_fields_save_meta_box_data' ) )
return;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if ( ! current_user_can( 'edit_post', $post_id ) )
return;
if ( ! isset( $_POST['meta_fields_book_title'] ) )
return;
if ( ! isset( $_POST['meta_fields_book_author'] ) )
return;
$title = sanitize_text_field( $_POST['meta_fields_book_title'] );
$author = sanitize_text_field( $_POST['meta_fields_book_author'] );
update_post_meta( $post_id, '_meta_fields_book_title', $title );
update_post_meta( $post_id, '_meta_fields_book_author', $author );
}
add_action( 'save_post', 'meta_fields_save_meta_box_data' );
// save metadata function meta_fields_save_meta_box_data( $post_id ) { if ( ! isset( $_POST['meta_fields_meta_box_nonce'] ) ) return; if ( ! wp_verify_nonce( $_POST['meta_fields_meta_box_nonce'], 'meta_fields_save_meta_box_data' ) ) return; if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return; if ( ! current_user_can( 'edit_post', $post_id ) ) return; if ( ! isset( $_POST['meta_fields_book_title'] ) ) return; if ( ! isset( $_POST['meta_fields_book_author'] ) ) return; $title = sanitize_text_field( $_POST['meta_fields_book_title'] ); $author = sanitize_text_field( $_POST['meta_fields_book_author'] ); update_post_meta( $post_id, '_meta_fields_book_title', $title ); update_post_meta( $post_id, '_meta_fields_book_author', $author ); } add_action( 'save_post', 'meta_fields_save_meta_box_data' );
// save metadata
function meta_fields_save_meta_box_data( $post_id ) {
if ( ! isset( $_POST['meta_fields_meta_box_nonce'] ) )
return;
if ( ! wp_verify_nonce( $_POST['meta_fields_meta_box_nonce'], 'meta_fields_save_meta_box_data' ) )
return;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if ( ! current_user_can( 'edit_post', $post_id ) )
return;
if ( ! isset( $_POST['meta_fields_book_title'] ) )
return;
if ( ! isset( $_POST['meta_fields_book_author'] ) )
return;
$title = sanitize_text_field( $_POST['meta_fields_book_title'] );
$author = sanitize_text_field( $_POST['meta_fields_book_author'] );
update_post_meta( $post_id, '_meta_fields_book_title', $title );
update_post_meta( $post_id, '_meta_fields_book_author', $author );
}
add_action( 'save_post', 'meta_fields_save_meta_box_data' );

同樣,請檢視線上文件以瞭解細節。這裡我們只指出元鍵前面的下劃線字元 (_) 。這告訴WordPress從預設的自定義欄位列表中隱藏這些自定義欄位的鍵,並使你的自定義欄位只在你的自定義元框中可見。

下面的圖片顯示了自定義元框在經典編輯器中的樣子:

經典編輯器中的一個自定義元框

經典編輯器中的一個自定義元框。

現在,如果你禁用經典編輯器外掛,並檢查在區塊編輯器中發生的情況,你會看到元框仍然出現並工作,但不完全是以你可能期望的方式。

我們的目標是建立一個系統,用於管理附加在部落格文章或自定義文章型別上的後設資料,並將其無縫整合到塊編輯器中。由於這個原因,到目前為止所顯示的程式碼只需要確保與經典編輯器的向後相容。

因此,在繼續前進之前,我們將通過在 add_meta_box 函式中新增 __back_compat_meta_box 標誌來告訴WordPress從區塊編輯器中移除自定義元框(參見元框相容標誌向後相容)。

讓我們回到註冊後設資料框的回撥函式,並將其修改如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// register meta box
function meta_fields_add_meta_box(){
add_meta_box(
'meta_fields_meta_box',
__( 'Book details' ),
'meta_fields_build_meta_box_callback',
'post',
'side',
'default',
// hide the meta box in Gutenberg
array('__back_compat_meta_box' => true)
);
}
// register meta box function meta_fields_add_meta_box(){ add_meta_box( 'meta_fields_meta_box', __( 'Book details' ), 'meta_fields_build_meta_box_callback', 'post', 'side', 'default', // hide the meta box in Gutenberg array('__back_compat_meta_box' => true) ); }
// register meta box
function meta_fields_add_meta_box(){
add_meta_box(
'meta_fields_meta_box', 
__( 'Book details' ), 
'meta_fields_build_meta_box_callback', 
'post', 
'side',
'default',
// hide the meta box in Gutenberg
array('__back_compat_meta_box' => true)
);
}

儲存該外掛檔案,然後回到你的WordPress管理區。現在,你不應該再在塊狀編輯器中看到自定義元框了。如果你重新啟用經典編輯器,你的自定義元框就會重新顯示出來。

在古騰堡區塊編輯中新增自定義元欄位(三個選項)

在我們之前關於Gutenberg區塊開發的文章中,我們詳細介紹了編輯器、它的各個部分,以及如何開發靜態區塊動態區塊

正如我們提到的,在這篇文章中,我們將更進一步,討論如何為部落格文章新增自定義元欄位。

在Gutenberg中,有幾種方法來儲存和使用文章後設資料。這裡我們將介紹以下內容:

  1. 建立一個自定義塊來儲存和顯示自定義元欄位
  2. 在文件側邊欄中新增一個自定義元框
  3. 新增一個自定義側邊欄來管理帖子的後設資料

建立一個自定義區塊來儲存和顯示自定義元欄位

在本節中,我們將向你展示如何在一個動態區塊中建立和管理自定義元欄位。根據Block Editor Handbook,一個文章元欄位 “是一個WordPress物件,用來儲存關於一個文章的額外資料”,我們需要首先註冊一個新的元欄位,然後才能使用它。

註冊自定義元欄位

在註冊一個自定義元欄位之前,你需要確保將使用它的文章型別支援自定義欄位。此外,當你註冊一個自定義元欄位時,你應該把 show_in_rest 引數設定為 true

現在,回到外掛檔案中。新增以下程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* Register the custom meta fields
*/
function meta_fields_register_meta() {
$metafields = [ '_meta_fields_book_title', '_meta_fields_book_author' ];
foreach( $metafields as $metafield ){
// Pass an empty string to register the meta key across all existing post types.
register_post_meta( '', $metafield, array(
'show_in_rest' => true,
'type' => 'string',
'single' => true,
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => function() {
return current_user_can( 'edit_posts' );
}
));
}
}
add_action( 'init', 'meta_fields_register_meta' );
/** * Register the custom meta fields */ function meta_fields_register_meta() { $metafields = [ '_meta_fields_book_title', '_meta_fields_book_author' ]; foreach( $metafields as $metafield ){ // Pass an empty string to register the meta key across all existing post types. register_post_meta( '', $metafield, array( 'show_in_rest' => true, 'type' => 'string', 'single' => true, 'sanitize_callback' => 'sanitize_text_field', 'auth_callback' => function() { return current_user_can( 'edit_posts' ); } )); } } add_action( 'init', 'meta_fields_register_meta' );
/**
* Register the custom meta fields
*/
function meta_fields_register_meta() {
$metafields = [ '_meta_fields_book_title', '_meta_fields_book_author' ];
foreach( $metafields as $metafield ){
// Pass an empty string to register the meta key across all existing post types.
register_post_meta( '', $metafield, array(
'show_in_rest' => true,
'type' => 'string',
'single' => true,
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => function() { 
return current_user_can( 'edit_posts' );
}
));
}  
}
add_action( 'init', 'meta_fields_register_meta' );

register_post_meta 為指定的帖子型別註冊了一個元鍵。在上面的程式碼中,我們為你網站上註冊的所有支援自定義欄位的帖子型別註冊了兩個自定義元欄位。更多資訊請參見函式參考

完成後,開啟你的塊外掛的src/index.js檔案。

在客戶端註冊區塊型別

現在導航到wp-content/plugins/metadata-block/src資料夾,開啟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 metadata from './block.json';
registerBlockType( metadata.name, {
edit: Edit,
} );
import { registerBlockType } from '@wordpress/blocks'; import './style.scss'; import Edit from './edit'; import metadata from './block.json'; registerBlockType( metadata.name, { edit: Edit, } );
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import metadata from './block.json';
registerBlockType( metadata.name, {
edit: Edit,
} );

對於靜態區塊,我們也會看到一個 save 函式功能。在這種情況下,由於我們安裝了一個動態區塊,所以沒有 save 函式。前臺顯示的內容將通過PHP動態生成。

建立區塊型別

導航到wp-content/plugins/metadata-block/src資料夾,開啟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() }>
{ __( 'Meta Fields – hello from the editor!', 'metadata-block' ) }
</p>
);
}
import { __ } from '@wordpress/i18n'; import { useBlockProps } from '@wordpress/block-editor'; import './editor.scss'; export default function Edit() { return ( <p { ...useBlockProps() }> { __( 'Meta Fields – hello from the editor!', 'metadata-block' ) } </p> ); }
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p { ...useBlockProps() }>
{ __( 'Meta Fields – hello from the editor!', 'metadata-block' ) }
</p>
);
}

在這裡,你將新增程式碼來生成要在編輯器中呈現的區塊。

第一步是匯入構建區塊所需的元件和函式。這裡是完整的依賴性列表:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { TextControl, PanelBody, PanelRow } from '@wordpress/components';
import './editor.scss';
import { __ } from '@wordpress/i18n'; import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; import { useEntityProp } from '@wordpress/core-data'; import { TextControl, PanelBody, PanelRow } from '@wordpress/components'; import './editor.scss';
import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { TextControl, PanelBody, PanelRow } from '@wordpress/components';
import './editor.scss';

如果你讀過我們以前的文章,你應該對這些 import 宣告中的許多內容很熟悉。這裡我們只指出其中的幾個:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data'; import { useEntityProp } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';

一旦你匯入了這些依賴,下面是你如何在 Edit() 函式中 useSelect 和 useEntityProp :

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const postType = useSelect(
( select ) => select( 'core/editor' ).getCurrentPostType(),
[]
);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const postType = useSelect( ( select ) => select( 'core/editor' ).getCurrentPostType(), [] ); const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const postType = useSelect(
( select ) => select( 'core/editor' ).getCurrentPostType(),
[]
);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );

這段程式碼提供了當前的 postType,一個元欄位的物件(meta),以及一個更新它們的setter函式(setMeta)。

現在用下面的程式碼替換當前 Edit() 函式的程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function Edit() {
const blockProps = useBlockProps();
const postType = useSelect(
( select ) => select( 'core/editor' ).getCurrentPostType(),
[]
);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const bookTitle = meta[ '_meta_fields_book_title' ];
const bookAuthor = meta[ '_meta_fields_book_author' ];
const updateBookTitleMetaValue = ( newValue ) => {
setMeta( { ...meta, _meta_fields_book_title: newValue } );
};
const updateBookAuthorMetaValue = ( newValue ) => {
setMeta( { ...meta, _meta_fields_book_author: newValue } );
};
return ( ... );
}
export default function Edit() { const blockProps = useBlockProps(); const postType = useSelect( ( select ) => select( 'core/editor' ).getCurrentPostType(), [] ); const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' ); const bookTitle = meta[ '_meta_fields_book_title' ]; const bookAuthor = meta[ '_meta_fields_book_author' ]; const updateBookTitleMetaValue = ( newValue ) => { setMeta( { ...meta, _meta_fields_book_title: newValue } ); }; const updateBookAuthorMetaValue = ( newValue ) => { setMeta( { ...meta, _meta_fields_book_author: newValue } ); }; return ( ... ); }
export default function Edit() {
const blockProps = useBlockProps();
const postType = useSelect(
( select ) => select( 'core/editor' ).getCurrentPostType(),
[]
);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const bookTitle = meta[ '_meta_fields_book_title' ];
const bookAuthor = meta[ '_meta_fields_book_author' ];
const updateBookTitleMetaValue = ( newValue ) => {
setMeta( { ...meta, _meta_fields_book_title: newValue } );
};
const updateBookAuthorMetaValue = ( newValue ) => {
setMeta( { ...meta, _meta_fields_book_author: newValue } );
};
return ( ... );
}

Again:

  • We used useSelect to get the current post type.我們使用 useSelect 來獲取當前的文章型別。
  • useEntityProp 返回一個元欄位的陣列和一個setter函式來設定新的元值。
  • updateBookTitleMetaValue 和 updateBookAuthorMetaValue是兩個事件處理程式,用於儲存元欄位值。

下一步是建立由 Edit() 函式返回的JSX(JavaScript XML)程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function Edit() {
...
return (
<>
<InspectorControls>
<PanelBody
title={ __( 'Book Details' )}
initialOpen={true}
>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Book title' )}
value={ bookTitle }
onChange={ updateBookTitleMetaValue }
/>
</fieldset>
</PanelRow>
<PanelRow>
<fieldset>
<TextControl
label={ __( 'Book author' ) }
value={ bookAuthor }
onChange={ updateBookAuthorMetaValue }
/>
</fieldset>
</PanelRow>
</PanelBody>
</InspectorControls>
<div { ...blockProps }>
<RichText
tagName="h3"
onChange={ updateBookTitleMetaValue }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ bookTitle }
placeholder={ __( 'Write your text...' ) }
/>
<TextControl
label="Book Author"
value={ bookAuthor }
onChange={ updateBookAuthorMetaValue }
/>
</div>
</>
);
}
export default function Edit() { ... return ( <> <InspectorControls> <PanelBody title={ __( 'Book Details' )} initialOpen={true} > <PanelRow> <fieldset> <TextControl label={__( 'Book title' )} value={ bookTitle } onChange={ updateBookTitleMetaValue } /> </fieldset> </PanelRow> <PanelRow> <fieldset> <TextControl label={ __( 'Book author' ) } value={ bookAuthor } onChange={ updateBookAuthorMetaValue } /> </fieldset> </PanelRow> </PanelBody> </InspectorControls> <div { ...blockProps }> <RichText tagName="h3" onChange={ updateBookTitleMetaValue } allowedFormats={ [ 'core/bold', 'core/italic' ] } value={ bookTitle } placeholder={ __( 'Write your text...' ) } /> <TextControl label="Book Author" value={ bookAuthor } onChange={ updateBookAuthorMetaValue } /> </div> </> ); }
export default function Edit() {
...
return (
<>
<InspectorControls>
<PanelBody 
title={ __( 'Book Details' )}
initialOpen={true}
>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Book title' )}
value={ bookTitle }
onChange={ updateBookTitleMetaValue }
/>
</fieldset>
</PanelRow>
<PanelRow>
<fieldset>
<TextControl
label={ __( 'Book author' ) }
value={ bookAuthor }
onChange={ updateBookAuthorMetaValue }
/>
</fieldset>
</PanelRow>
</PanelBody>
</InspectorControls>
<div { ...blockProps }>
<RichText 
tagName="h3"
onChange={ updateBookTitleMetaValue }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ bookTitle }
placeholder={ __( 'Write your text...' ) }
/>
<TextControl
label="Book Author"
value={ bookAuthor }
onChange={ updateBookAuthorMetaValue }
/>
</div>
</>
);
}

RichText 元件提供了一個可編輯內容的輸入,而 TextControl 提供了簡單的文字欄位。

我們還建立了一個包含兩個輸入欄位的側邊欄面板,用來代替塊中包含的兩個表單控制元件。

儲存檔案並回到編輯器。從區塊插入器中新增Meta Fields區塊,並填入書名和作者。

一個自定義區塊包括兩個自定義元欄位

一個自定義區塊包括兩個自定義元欄位。

你會注意到,每當你改變塊中欄位的值時,側邊欄中相應文字欄位的值也會改變。

接下來,我們要建立PHP程式碼,生成HTML,在前臺顯示。

在前臺顯示該區塊

在你的程式碼編輯器中再次開啟主PHP檔案,重寫生成塊輸出的回撥函式,如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function meta_fields_metadata_block_block_init() {
register_block_type(
__DIR__ . '/build',
array(
'render_callback' => 'meta_fields_metadata_block_render_callback',
)
);
}
add_action( 'init', 'meta_fields_metadata_block_block_init' );
function meta_fields_metadata_block_render_callback( $attributes, $content, $block ) {
$book_title = get_post_meta( get_the_ID(), '_meta_fields_book_title', true );
$book_author = get_post_meta( get_the_ID(), '_meta_fields_book_author', true );
$output = "";
if( ! empty( $book_title ) ){
$output .= '<h3>' . esc_html( $book_title ) . '</h3>';
}
if( ! empty( $book_author ) ){
$output .= '<p>' . __( 'Book author: ' ) . esc_html( $book_author ) . '</p>';
}
if( strlen( $output ) > 0 ){
return '<div ' . get_block_wrapper_attributes() . '>' . $output . '</div>';
} else {
return '<div ' . get_block_wrapper_attributes() . '>' . '<strong>' . __( 'Sorry. No fields available here!' ) . '</strong>' . '</div>';
}
}
function meta_fields_metadata_block_block_init() { register_block_type( __DIR__ . '/build', array( 'render_callback' => 'meta_fields_metadata_block_render_callback', ) ); } add_action( 'init', 'meta_fields_metadata_block_block_init' ); function meta_fields_metadata_block_render_callback( $attributes, $content, $block ) { $book_title = get_post_meta( get_the_ID(), '_meta_fields_book_title', true ); $book_author = get_post_meta( get_the_ID(), '_meta_fields_book_author', true ); $output = ""; if( ! empty( $book_title ) ){ $output .= '<h3>' . esc_html( $book_title ) . '</h3>'; } if( ! empty( $book_author ) ){ $output .= '<p>' . __( 'Book author: ' ) . esc_html( $book_author ) . '</p>'; } if( strlen( $output ) > 0 ){ return '<div ' . get_block_wrapper_attributes() . '>' . $output . '</div>'; } else { return '<div ' . get_block_wrapper_attributes() . '>' . '<strong>' . __( 'Sorry. No fields available here!' ) . '</strong>' . '</div>'; } }
function meta_fields_metadata_block_block_init() {
register_block_type(
__DIR__ . '/build',
array(
'render_callback' => 'meta_fields_metadata_block_render_callback',
)
);
}
add_action( 'init', 'meta_fields_metadata_block_block_init' );
function meta_fields_metadata_block_render_callback( $attributes, $content, $block ) {
$book_title = get_post_meta( get_the_ID(), '_meta_fields_book_title', true );
$book_author = get_post_meta( get_the_ID(), '_meta_fields_book_author', true );
$output = "";
if( ! empty( $book_title ) ){
$output .= '<h3>' . esc_html( $book_title ) . '</h3>';
}
if( ! empty( $book_author ) ){
$output .= '<p>' . __( 'Book author: ' ) . esc_html( $book_author ) . '</p>';
}
if( strlen( $output ) > 0 ){
return '<div ' . get_block_wrapper_attributes() . '>' . $output . '</div>';
} else {
return '<div ' . get_block_wrapper_attributes() . '>' . '<strong>' . __( 'Sorry. No fields available here!' ) . '</strong>' . '</div>';
}
}

這段程式碼是不言自明的。首先,我們使用 get_post_meta 來檢索自定義元欄位的值。然後,我們使用這些值來構建塊的內容。最後,回撥函式返回該塊的HTML。

塊已經準備好被使用了。我們有意讓這個例子中的程式碼儘可能簡單,但使用Gutenberg的本地元件,你可以建立更高階的塊,並從WordPress的自定義元欄位中獲得最大的收益。

一個包括幾個元欄位的自定義區塊

一個包括幾個元欄位的自定義區塊。

在我們的例子中,我們使用 h3 和 p 元素來建立前端的區塊。

但是你可以用很多方式來顯示資料。下面的圖片顯示了一個簡單的無序的元欄位列表。

前臺的一個示例區塊

前臺的一個示例區塊。

你可以在這個公開的gist中找到這個例子的完整程式碼。

在文件側邊欄新增一個自定義元框

第二個選擇是使用一個外掛將自定義元欄位附加到帖子上,該外掛在文件側邊欄生成一個設定面板。

這個過程與前面的例子很相似,只是在這種情況下,我們將不需要一個區塊來管理後設資料。我們將按照以下步驟建立一個元件,在文件側邊欄中生成一個包括一系列控制元件的面板:

  1. 用create-block建立一個新的區塊外掛
  2. 為經典編輯器註冊一個自定義元域框
  3. 通過register_post_meta()函式在主外掛檔案中註冊自定義元域
  4. 在index.js檔案中註冊一個外掛
  5. 使用內建的Gutenberg元件構建該元件

用create-block建立一個新的區塊外掛

要建立一個新的區塊外掛,請按照上一節的步驟進行。你可以建立一個新的外掛,或者編輯我們在前面的例子中建立的指令碼。

為經典編輯器註冊一個自定義元域框

接下來,你需要註冊一個自定義元框,以確保仍然使用經典編輯器的WordPress網站向後相容。這個過程與上一節所述的相同。

通過register_post_meta()函式在主外掛檔案中註冊自定義元域

下一步是通過 register_post_meta() 函式在主外掛檔案中註冊自定義元域。同樣,你可以按照前面的例子

在index.js檔案中註冊一個外掛

一旦你完成了前面的步驟,現在是時候在index.js檔案中註冊一個外掛來渲染一個自定義元件了。

在註冊該外掛之前,在該外掛的src資料夾內建立一個components資料夾。在components資料夾內,建立一個新的MetaBox.js檔案。你可以選擇任何你認為對你的元件有利的名字。只要確保遵循React中命名的最佳實踐

在繼續前進之前,從你的命令列工具中安裝 @wordpress/plugins 模組 。

停止程序(mac),安裝模組並再次啟動程序:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
^C
npm install @wordpress/plugins --save
npm start
^C npm install @wordpress/plugins --save npm start
^C
npm install @wordpress/plugins --save
npm start

一旦完成,開啟你的外掛的index.js檔案,新增以下程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* Registers a plugin for adding items to the Gutenberg Toolbar
*
* @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/
*/
import { registerPlugin } from '@wordpress/plugins';
import MetaBox from './components/MetaBox';
/** * Registers a plugin for adding items to the Gutenberg Toolbar * * @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/ */ import { registerPlugin } from '@wordpress/plugins'; import MetaBox from './components/MetaBox';
/**
* Registers a plugin for adding items to the Gutenberg Toolbar
*
* @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/
*/
import { registerPlugin } from '@wordpress/plugins';
import MetaBox from './components/MetaBox';

這段程式碼是不言自明的。然而,我們想花點時間為那些沒有高階React技能的讀者詳細介紹一下這兩條 import 語句。

在第一條 import 語句中,我們將函式的名稱用大括號括起來。在第二條 import 語句中,元件的名字沒有用大括號括起來。

Info

不帶大括號的 import 語句用於匯入預設匯出。帶大括號的 import 語句用於匯入一個命名的匯出。有關其他細節,請參閱以下資源:

接下來,註冊你的外掛:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
registerPlugin( 'metadata-plugin', {
render: MetaBox
} );
registerPlugin( 'metadata-plugin', { render: MetaBox } );
registerPlugin( 'metadata-plugin', {
render: MetaBox
} );

registerPlugin 簡單地註冊了一個外掛。該函式接受兩個引數:

  • 一個唯一的字串,用於識別該外掛
  • 一個外掛設定的物件。注意,必須指定 render 屬性,並且必須是一個有效的函式。

使用內建的Gutenberg元件構建該元件

現在是時候建立我們的React元件了。開啟MetaBox.js檔案(或者你叫它什麼),新增以下匯入語句:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { PanelRow, TextControl, DateTimePicker } from '@wordpress/components';
import { __ } from '@wordpress/i18n'; import { compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; import { PanelRow, TextControl, DateTimePicker } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { PanelRow, TextControl, DateTimePicker } from '@wordpress/components';
  • compose 函式執行函式組合,意味著一個函式的結果被傳遞給另一個函式。在你使用 compose 之前,你可能需要安裝相應的模組。
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    npm install @wordpress/compose --save
    npm install @wordpress/compose --save
    npm install @wordpress/compose --save

    我們稍後將看到 compose 函式的執行。

  • withSelect 和 withDispatch 是兩個高階元件,允許你從WordPress商店獲取或排程資料。withSelect 用於使用註冊的選擇器注入源自狀態的道具,withDispatch 用於使用註冊的動作建立者排程道具。
  • PluginDocumentSettingPanel 渲染文件側邊欄的專案(見Github上的原始碼)。

接下來,你將建立元件,在文件側邊欄顯示元框面板。在你的MetaBox.js檔案中,新增以下程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const MetaBox = ( { postType, metaFields, setMetaFields } ) => {
if ( 'post' !== postType ) return null;
return(
<PluginDocumentSettingPanel
title={ __( 'Book details' ) }
icon="book"
initialOpen={ false }
>
<PanelRow>
<TextControl
value={ metaFields._meta_fields_book_title }
label={ __( "Title" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl
value={ metaFields._meta_fields_book_author }
label={ __( "Author" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl
value={ metaFields._meta_fields_book_publisher }
label={ __( "Publisher" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) }
/>
</PanelRow>
<PanelRow>
<DateTimePicker
currentDate={ metaFields._meta_fields_book_date }
onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) }
__nextRemoveHelpButton
__nextRemoveResetButton
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
const applyWithSelect = withSelect( ( select ) => {
return {
metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
postType: select( 'core/editor' ).getCurrentPostType()
};
} );
const applyWithDispatch = withDispatch( ( dispatch ) => {
return {
setMetaFields ( newValue ) {
dispatch('core/editor').editPost( { meta: newValue } )
}
}
} );
export default compose([
applyWithSelect,
applyWithDispatch
])(MetaBox);
const MetaBox = ( { postType, metaFields, setMetaFields } ) => { if ( 'post' !== postType ) return null; return( <PluginDocumentSettingPanel title={ __( 'Book details' ) } icon="book" initialOpen={ false } > <PanelRow> <TextControl value={ metaFields._meta_fields_book_title } label={ __( "Title" ) } onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) } /> </PanelRow> <PanelRow> <TextControl value={ metaFields._meta_fields_book_author } label={ __( "Author" ) } onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) } /> </PanelRow> <PanelRow> <TextControl value={ metaFields._meta_fields_book_publisher } label={ __( "Publisher" ) } onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) } /> </PanelRow> <PanelRow> <DateTimePicker currentDate={ metaFields._meta_fields_book_date } onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) } __nextRemoveHelpButton __nextRemoveResetButton /> </PanelRow> </PluginDocumentSettingPanel> ); } const applyWithSelect = withSelect( ( select ) => { return { metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ), postType: select( 'core/editor' ).getCurrentPostType() }; } ); const applyWithDispatch = withDispatch( ( dispatch ) => { return { setMetaFields ( newValue ) { dispatch('core/editor').editPost( { meta: newValue } ) } } } ); export default compose([ applyWithSelect, applyWithDispatch ])(MetaBox);
const MetaBox = ( { postType, metaFields, setMetaFields } ) => {
if ( 'post' !== postType ) return null;
return(
<PluginDocumentSettingPanel 
title={ __( 'Book details' ) } 
icon="book"
initialOpen={ false }
>
<PanelRow>
<TextControl 
value={ metaFields._meta_fields_book_title }
label={ __( "Title" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl 
value={ metaFields._meta_fields_book_author }
label={ __( "Author" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl 
value={ metaFields._meta_fields_book_publisher }
label={ __( "Publisher" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) }
/>
</PanelRow>
<PanelRow>
<DateTimePicker
currentDate={ metaFields._meta_fields_book_date }
onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) }
__nextRemoveHelpButton
__nextRemoveResetButton
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
const applyWithSelect = withSelect( ( select ) => {
return {
metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
postType: select( 'core/editor' ).getCurrentPostType()
};
} );
const applyWithDispatch = withDispatch( ( dispatch ) => {
return {
setMetaFields ( newValue ) {
dispatch('core/editor').editPost( { meta: newValue } )
}
}
} );
export default compose([
applyWithSelect,
applyWithDispatch
])(MetaBox);

讓我們來分解一下這段程式碼。

  • PluginDocumentSettingPanel 元素在Document側邊欄渲染了一個新的面板。我們設定了標題(”Book details”)和圖示,並將 initialOpen 設定為 false,這意味著最初面板是關閉的。
  • 在 PluginDocumentSettingPanel 中,我們有三個文字欄位和一個 DateTimePicker 元素,允許使用者設定出版日期。
  • withSelect 提供了對 select 函式的訪問,我們用它來檢索 metaFields 和 postTypewithDispatch 提供了對 dispatch函式的訪問,它允許更新後設資料值。
  • 最後, compose 函式允許我們將我們的元件與 withSelect 和 withDispatch 的高階元件進行組合。這使得元件可以訪問 metaFields 和 postType 屬性以及 setMetaFields 函式。

儲存你的MetaBox.js檔案,在你的WordPress開發網站上建立一個新的帖子,看看文件側邊欄。你應該看到新的圖書細節面板。

Gutenberg中的一個自定義元框面板

Gutenberg中的一個自定義元框面板。

現在執行你的測試。設定你的自定義元欄位的值並儲存帖子。然後重新載入頁面,檢查你輸入的值是否到位。

新增我們在上一節中建立的塊,並檢查一切是否正常工作。

新增自定義側邊欄以管理文章的後設資料

如果你有大量的自定義元欄位需要新增到你的文章或自定義文章型別中,你也可以專門為你的外掛建立一個自定義設定側邊欄。

這個過程與前面的例子非常相似,所以如果你已經理解了上一節所討論的步驟,你在為Gutenberg建立自定義側欄時不會有任何困難。

Again:

  1. 用create-block建立一個新的區塊外掛
  2. 為經典編輯器註冊一個自定義元域框
  3. 通過register_post_meta()函式在主外掛檔案中註冊自定義元域
  4. 在index.js檔案中註冊一個外掛
  5. 使用內建的Gutenberg元件構建該元件

用create-block工具建立一個新的區塊外掛

同樣,要建立一個新的區塊外掛,請遵循上面討論的步驟。你可以建立一個新的外掛,也可以編輯前面例子中建立的指令碼。

為經典編輯器註冊一個自定義元框

現在註冊一個自定義元框,以確保仍然使用經典編輯器的WordPress網站的向後相容性。這個過程與上一節所述的相同。

在主外掛檔案中註冊自定義元欄位

通過 register_post_meta() 函式在主外掛檔案中註冊自定義元欄位。

在index.js檔案中註冊一個外掛

現在在你的components資料夾中建立一個空的CustomSidebar.js檔案。

一旦完成,請修改你的index.js檔案,如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* Registers a plugin for adding items to the Gutenberg Toolbar
*
* @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/
*/
import { registerPlugin } from '@wordpress/plugins';
import CustomSidebar from './components/CustomSidebar';
// import MetaBox from './components/MetaBox';
registerPlugin( 'metadata-block', {
render: CustomSidebar
} );
/** * Registers a plugin for adding items to the Gutenberg Toolbar * * @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/ */ import { registerPlugin } from '@wordpress/plugins'; import CustomSidebar from './components/CustomSidebar'; // import MetaBox from './components/MetaBox'; registerPlugin( 'metadata-block', { render: CustomSidebar } );
/**
* Registers a plugin for adding items to the Gutenberg Toolbar
*
* @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/
*/
import { registerPlugin } from '@wordpress/plugins';
import CustomSidebar from './components/CustomSidebar';
// import MetaBox from './components/MetaBox';
registerPlugin( 'metadata-block', {
render: CustomSidebar
} );

通過上面的程式碼,我們首先匯入 CustomSidebar 元件,然後告訴 registerPlugin 函式來渲染新的元件。

使用內建的Gutenberg元件構建該元件

接下來,開啟CustomSidebar.js檔案,新增以下依賴項:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
import { PanelBody, PanelRow, TextControl, DateTimePicker } from '@wordpress/components';
import { __ } from '@wordpress/i18n'; import { compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post'; import { PanelBody, PanelRow, TextControl, DateTimePicker } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
import { PanelBody, PanelRow, TextControl, DateTimePicker } from '@wordpress/components';

你應該注意到,我們正在匯入兩個新的元件:

  • PluginSidebar 在Gutenberg工具欄中新增了一個圖示,點選後會顯示一個側邊欄,包括<PluginSidebar /> 元素中包裹的內容(該元件在GitHub上也有記錄)。
  • PluginSidebarMoreMenuItem renders a menu item under Plugins in More Menu dropdown and can be used to activate the corresponding PluginSidebar component (see also on GitHub).在更多下拉選單中的Plugins下渲染了一個選單項,可以用來啟用相應的 PluginSidebar 元件(也見GitHub上的文件)。

現在你可以建立你的自定義元件了:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const CustomSidebar = ( { postType, metaFields, setMetaFields } ) => {
if ( 'post' !== postType ) return null;
return (
<>
<PluginSidebarMoreMenuItem
target="metadata-sidebar"
icon="book"
>
Metadata Sidebar
</PluginSidebarMoreMenuItem>
<PluginSidebar
name="metadata-sidebar"
icon="book"
title="My Sidebar"
>
<PanelBody title="Book details" initialOpen={ true }>
<PanelRow>
<TextControl
value={ metaFields._meta_fields_book_title }
label={ __( "Title" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl
value={ metaFields._meta_fields_book_author }
label={ __("Author", "textdomain") }
onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl
value={ metaFields._meta_fields_book_publisher }
label={ __("Publisher", "textdomain") }
onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) }
/>
</PanelRow>
<PanelRow>
<DateTimePicker
currentDate={ metaFields._meta_fields_book_date }
onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) }
__nextRemoveHelpButton
__nextRemoveResetButton
/>
</PanelRow>
</PanelBody>
</PluginSidebar>
</>
)
}
const CustomSidebar = ( { postType, metaFields, setMetaFields } ) => { if ( 'post' !== postType ) return null; return ( <> <PluginSidebarMoreMenuItem target="metadata-sidebar" icon="book" > Metadata Sidebar </PluginSidebarMoreMenuItem> <PluginSidebar name="metadata-sidebar" icon="book" title="My Sidebar" > <PanelBody title="Book details" initialOpen={ true }> <PanelRow> <TextControl value={ metaFields._meta_fields_book_title } label={ __( "Title" ) } onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) } /> </PanelRow> <PanelRow> <TextControl value={ metaFields._meta_fields_book_author } label={ __("Author", "textdomain") } onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) } /> </PanelRow> <PanelRow> <TextControl value={ metaFields._meta_fields_book_publisher } label={ __("Publisher", "textdomain") } onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) } /> </PanelRow> <PanelRow> <DateTimePicker currentDate={ metaFields._meta_fields_book_date } onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) } __nextRemoveHelpButton __nextRemoveResetButton /> </PanelRow> </PanelBody> </PluginSidebar> </> ) }
const CustomSidebar = ( { postType, metaFields, setMetaFields } ) => {
if ( 'post' !== postType ) return null;
return (
<>
<PluginSidebarMoreMenuItem 
target="metadata-sidebar" 
icon="book"
>
Metadata Sidebar
</PluginSidebarMoreMenuItem>
<PluginSidebar 
name="metadata-sidebar" 
icon="book" 
title="My Sidebar"
>
<PanelBody title="Book details" initialOpen={ true }>
<PanelRow>
<TextControl 
value={ metaFields._meta_fields_book_title }
label={ __( "Title" ) }
onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl 
value={ metaFields._meta_fields_book_author }
label={ __("Author", "textdomain") }
onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) }
/>
</PanelRow>
<PanelRow>
<TextControl 
value={ metaFields._meta_fields_book_publisher }
label={ __("Publisher", "textdomain") }
onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) }
/>
</PanelRow>
<PanelRow>
<DateTimePicker
currentDate={ metaFields._meta_fields_book_date }
onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) }
__nextRemoveHelpButton
__nextRemoveResetButton
/>
</PanelRow>
</PanelBody>
</PluginSidebar>
</>
)
}

最後一步是用 withSelect 和 withDispatch 高階元件組成:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const applyWithSelect = withSelect( ( select ) => {
return {
metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
postType: select( 'core/editor' ).getCurrentPostType()
};
} );
const applyWithDispatch = withDispatch( ( dispatch ) => {
return {
setMetaFields ( newValue ) {
dispatch('core/editor').editPost( { meta: newValue } )
}
}
} );
export default compose([
applyWithSelect,
applyWithDispatch
])(CustomSidebar);
const applyWithSelect = withSelect( ( select ) => { return { metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ), postType: select( 'core/editor' ).getCurrentPostType() }; } ); const applyWithDispatch = withDispatch( ( dispatch ) => { return { setMetaFields ( newValue ) { dispatch('core/editor').editPost( { meta: newValue } ) } } } ); export default compose([ applyWithSelect, applyWithDispatch ])(CustomSidebar);
const applyWithSelect = withSelect( ( select ) => {
return {
metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
postType: select( 'core/editor' ).getCurrentPostType()
};
} );
const applyWithDispatch = withDispatch( ( dispatch ) => {
return {
setMetaFields ( newValue ) {
dispatch('core/editor').editPost( { meta: newValue } )
}
}
} );
export default compose([
applyWithSelect,
applyWithDispatch
])(CustomSidebar);

儲存你的修改,然後檢查編輯器介面。如果你開啟Options下拉選單,你會在外掛部分看到一個新的Metadata Sidebar專案。點選這個新專案將啟用你全新的自定義側邊欄。

外掛側邊欄更多選單項

PluginSidebarMoreMenuItem元件在Options – Plugins下增加了一個選單項。

當你點選右上角的書籍圖示時,也會發生同樣的情況。

外掛設定側邊欄

外掛設定側邊欄。

現在回到你的開發網站,並建立一個新的部落格文章。填寫你的元欄位,然後將該塊新增到編輯器的畫布上。它應該包括你在自定義側邊欄中輸入的相同元值。

儲存文章並在前臺預覽頁面。你應該看到你的卡片包括書名、作者、出版商和出版日期。

你可以在這個公開的gist中找到這篇文章的完整程式碼。

進一步閱讀

在這篇文章中,我們涵蓋了多個主題,從選擇器到高階元件以及更多。我們在文章中也連結了我們所使用的頂級資源作為參考。

但是,如果你想更深入地瞭解這些主題,你可能還想檢視以下額外的資源:

Gutenberg文件和官方WordPress資源

更多官方資源

來自社羣的其他資源

本站可參考的文章

小結

在這篇關於Gutenberg區塊開發系列的第三篇文章中,我們涵蓋了新的高階主題,這些主題應該使之前關於靜態動態區塊開發的文章中所概述的情況更加完整。

你現在應該能夠利用Gutenberg中自定義欄位的潛力,並建立更先進、更實用的WordPress網站。

但還有更多。憑藉你從我們關於區塊開發的文章中獲得的技能,你也應該對如何在WordPress之外開發React元件有一個好的想法。畢竟,Gutenberg是一個基於React的SPA。

現在就看你的了! 你已經建立了使用自定義元欄位的Gutenberg區塊了嗎?請在下面的評論中與我們分享你的創作。

評論留言