四天連假終於有時間再戰 WooCommerce 推播通知外掛的區塊開發,研究許久才搞定 LINE 登入按鈕,這顆按鈕支援所有的區塊功能,像是對齊、設定連結、樣式、寬度、顏色,看起來就跟原生的按鈕一模一樣,事實上,它就是原生的區塊按鈕無誤XD
當我在規劃時我就希望可以做到像是原生按鈕一樣,可以彈性的控制顏色、大小等等以提供使用者一致的操作體驗,於是我去翻 Gutenberg 的原始碼,不看還好,看了之後快暈倒,光是一顆按鈕它的程式碼跟資料結構就複雜到讓我想棄守,邊看邊在心裡碎唸,我只是要做一顆按鈕需要這麼麻煩嗎?
於是換個念頭,何不直接拿原生的按鈕再加入我需要的功能就好?研究了開發手冊發現到還真的可以這樣幹,關鍵字叫做 Innerblocks 內部區塊,透過內部區塊的範本,我可以做到在加入我的區塊時,把既有的區塊放在裡面,而內部區塊還可以保有原先的各項設定功能。
我的 LINE 登入按鈕區塊 HTML 結構長這樣:
最外層的 <div>
是我的區塊,而 wp:button
是內建的按鈕區塊,我把按鈕包在我的區塊中,這樣我就不用實作按鈕的設定功能,要使用內部區塊要先匯入 block-editor
的 InnerBlocks
,然後先定義範本裡面要放哪些區塊,同時設定區塊的初始值,最後再使用 <InnerBlocks />
元件加入範本:
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor'
import { useSelect } from '@wordpress/data'
export default function Edit({attributes,setAttributes}) {
const blockProps = useBlockProps({
className: "wc-notify-line-login"
});
const permalink = useSelect(
( select ) => select( 'core/editor' ).getPermalink(),
[]
);
const MY_TEMPLATE = [
[ 'core/button', {
text:`<span><img src="${lineLoginButtonParams.buttonIconUrl}">LINE Login</span>`,
url:permalink+'?lgmode=true',
} ],
];
return (
<div {...blockProps}>
<InnerBlocks template={ MY_TEMPLATE} templateLock="all" />
</div>
);
}
跟一般按鈕不同,我想要我的 LINE 登入按鈕一加入時就是綠底白字,並且帶好登入連結,要做到這件事可以指定區塊的初始參數,按鈕區塊的初始值可以在原始碼 block.json
裡面的 attributes
跟 supports
找到。
像是 text
是按鈕的預設文字,url
是預設連結,但有些屬性我給了卻沒作用,像是按鈕顏色 backgroundColor
、文字顏色 textColor
等屬性無法,實測結果感覺是樣式類的屬性都無法給預設值,因此最後都還是用 CSS 來覆寫預設樣式的部分。
其次我要在按鈕文字的前方加入 LINE 的圖標,我想到的做法是把圖標的檔案路徑從 PHP 取得後寫入 JS 變數,讓按鈕區塊可以讀取,也就是 <img src="${lineLoginButtonParams.buttonIconUrl}">
這個部分,註冊 JS 變數的部分我依舊是使用熟悉的 wp_localize_script
來做:
function wc_notify_line_button_enqueue_scripts() {
$enqueue = new \WPackio\Enqueue( 'woocommerceNotify', 'assets/dist', '1.0.0', 'plugin', __FILE__ );
$assets = $enqueue->enqueue(
'blocks',
'lineLoginButton',
array(
'js_dep' => array( 'wp-blocks', 'wp-components', 'wp-editor', 'wp-i18n' ),
)
);
wp_localize_script(
array_pop( $assets['js'] )['handle'],
'lineLoginButtonParams',
array(
'buttonIconUrl' => WCNOTIFY_PLUGIN_URL . 'assets/img/dashicon.png',
)
);
}
add_action( 'init', 'wc_notify_line_button_enqueue_scripts' );
由於我使用的是 wpack.io 來引入 JS,因此在路徑取得的寫法是用它的 API,而註冊 JS 變數一樣是變數名稱+變數值,就能讓 edit.js
拿到從 PHP 產出的資料,有查到可以直接在 JS 使用 import
來引入圖片,但在編譯的過程中發生錯誤,就還是先用老方法了。
另一個我遇到的問題是內部區塊的樣式無法調整,也就是當我設定寬度或是置中對齊是沒有作用的,檢查後發現是因為多包了一層 <div>
而導致預設的樣式失效,這部分我花了一些時間把原本該套用的樣式再額外補上。
最後當看到按鈕可以設定寬度、大小、圓角半徑就覺得很感動,雖然我採用的是偷吃步,但至少已經達到我預期的成果,本來還想繼續研究如何增加按鈕的設定項以及自訂設定屬性,但在那之前可能還是要先把原始碼看懂才行了。