Ciptakan Pengalaman Mengedit WordPress yang Luar Biasa dan Hemat Waktu dengan Gutenberg InnerBlocks
Diterbitkan: 2023-02-12Jangan Ulangi Sendiri
Bagi pengembang, kemalasan bisa menjadi suatu kebajikan. Komponen yang dibuat dengan baik dan dapat digunakan kembali menghemat waktu dan memungkinkan penggunaan ulang dan konsistensi yang efisien. Ini cocok untuk menciptakan pengalaman pengeditan di WordPress, karena konsistensi melahirkan keakraban dan pengetahuan bagi mereka yang menggunakan situs web sehari-hari.
WordPress membuat banyak kebisingan dengan merilis editor blok Gutenberg, yang sekarang hanya dikenal sebagai “The Editor.” Untuk pengeditan, penyusunan, dan penerbitan konten, ini memberikan pengalaman yang luar biasa, jauh lebih baik daripada WYSIWYG yang lebih lama. Sebagai pengembang, saya ingin memberikan pengalaman pengeditan terbaik untuk klien saya, saya ingin memanfaatkan fungsionalitas inti, dan saya tidak ingin menemukan kembali kemudi. Untungnya, WordPress memungkinkan kita melakukan semua itu dengan blok khusus.
Masukkan InnerBlock
InnerBlocks adalah fitur hebat di editor WordPress. Pengembang dapat menggunakan blok inti seperti paragraf, judul, dan tombol untuk menciptakan pengalaman yang konsisten bagi klien. Alih-alih menulis ulang bagian teks dan mendeklarasikan ulang bidang, klien mendapatkan pengalaman yang mereka kenal; mengedit dan menggabungkan blok yang sama. Mari kita lihat blok yang mungkin perlu kita buat untuk klien, dan lihat bagaimana InnerBlocks dapat membantu kita mencapainya.
Membangun Blok dengan InnerBlocks
Mari kita periksa blok ini dan pertimbangkan bagaimana kita bisa membangunnya. Alat umum yang kami gunakan saat membuat blok adalah Bidang Kustom Lanjutan (ACF). ACF Pro menambahkan dukungan blok khusus, yang memungkinkan pengembang menulis blok dalam PHP untuk editor dan ujung depan. Itu juga memungkinkan kita menggunakan bidang khusus — sebuah paradigma yang akrab dengan banyak pengembang WordPress. ACF mendukung InnerBlocks, artinya kita dapat membuat blok khusus, tetapi bahkan tidak perlu menulis kode khusus untuk tajuk, paragraf, atau tombol tersebut.
Dengan Blok ACF, kami dapat memanfaatkan blok inti untuk membuat pengalaman pengeditan yang hebat untuk semua teks yang kami lihat di blok ini. Opsi potensial lainnya adalah menggunakan pola blok, tetapi sebagai pengembang dan kurator pengalaman WordPress yang fantastis, membuat blok khusus mencapai tujuan yang diinginkan.
Blokir Kode Pendaftaran
Berikut kode untuk mendaftarkan blok ACF khusus kami. Baca lebih lanjut tentang penggunaan fungsi acf_register_block_type di sini.
<?php /** * Template for registering an ACF powered custom block. * * More info: https://www.advancedcustomfields.com/resources/blocks/ */ /** * Register the block. */ add_action( 'acf/init', function() { /** * ACF block registration options here: https://www.advancedcustomfields.com/resources/acf_register_block_type/ */ acf_register_block_type( array( 'name' => 'call-to-action-demo', // JS will register as: acf/{block-name}. 'title' => __( 'Call to Action ACF Demo', 'locale' ), 'description' => __( 'A custom ACF Call to Action block.', 'locale' ), 'render_template' => 'partials/blocks/call-to-action-demo.php', // Change to block template. 'category' => 'design', // Category in the block inserter. 'keywords' => array( 'action', 'buttons', 'cta' ), // Searchable keywords. 'supports' => array( 'align' => false, // Disable support for align. 'anchor' => true, // Enable support for anchor. 'jsx' => true, // Enable support for JSX. 'mode' => false, // Disable ACF block edit/preview mode switching as we are only using InnerBlocks for editable content. ), ) ); } );
Mari kita pecahkan kodenya. Kami menggunakan fungsi acf_register_block_type untuk mendaftarkan blok kami, dan kami meneruskan serangkaian argumen yang menentukan blok kami dan mengaktifkan dan menonaktifkan fungsionalitas.
- Perhatikan bahwa kami mengikuti prosedur yang disarankan untuk menambahkan nama unik untuk blok kami, serta judul dan deskripsi yang dapat dibaca manusia. Kami menunjuk ke template render, di mana kami akan mengatur template PHP kami untuk blok nanti. Kami juga telah menambahkan kategori di mana kami ingin blok kami dikelompokkan di Block Inserter.
- Kami memiliki kata kunci yang dapat dicari untuk membuat blok lebih mudah dicari di penyisip.
- Kami menambahkan larik 'mendukung' untuk mengaktifkan fungsionalitas seperti menyetel jangkar HTML dan kami telah menonaktifkan perataan karena blok ini akan selalu berada di tengah halaman.
- Yang mendukung array adalah tempat kami mengaktifkan keajaiban InnerBlocks! Menyetel 'jsx' ke true memberi tahu ACF bahwa kami akan mendukung rendering template React jsx di dalam blok kami.
Mari tinjau konten yang kita butuhkan di blok kita:
- Menuju
- Teks paragraf
- Tombol untuk mengambil tindakan!
Sekarang, biasanya kami akan menetapkan bidang ke blok kami, seperti yang diuraikan di sini. Namun dalam kasus ini, kita tidak perlu melakukannya—kita dapat memanfaatkan blok inti untuk mencapai semua ini. Jika blok memerlukan latar belakang gambar, misalnya, menambahkan bidang gambar ACF ke blok bisa menjadi cara yang bagus untuk mencapainya. Untuk saat ini, mari kita tetap menggunakan contoh InnerBlocks kita dan beralih ke template.
Templat Blok
Ini template untuk blok baru. Pastikan untuk mengarahkan pendaftaran blok ke lokasi templat blok. Praktik yang umum adalah meletakkan ini di folder sebagian di tema.
<?php /** * ACF Call to Action example block template. * * More info: https://www.advancedcustomfields.com/resources/acf_register_block_type/ * * @param array $block The block settings and attributes. * @param string $content The block inner HTML (empty). * @param bool $is_preview True during AJAX preview. * @param (int|string) $post_id The post ID this block is saved to. * */ // Create id attribute allowing for custom "anchor" value. $block_ . $block['id']; if ( ! empty( $block['anchor'] ) ) { $block_id = $block['anchor']; } // Create class attribute allowing for custom "className" and "align" values. $class_name = 'acf-call-to-action-demo'; if ( ! empty( $block['className'] ) ) { $class_name .= ' ' . $block['className']; } if ( ! empty( $block['align'] ) ) { $class_name .= ' align' . $block['align']; } ?> <div class="<?php echo esc_html( $class_name ); ?>"> <div class="cta__inner"> <?php // Set up innerBlocks and provide a template. // Restrict InnerBlocks to allowed block list. $allowed_blocks = array( 'core/heading', 'core/paragraph', 'core/buttons' ); // Start InnerBlocks with a template. $template = array( array( 'core/heading', array( 'placeholder' => __( 'CTA Heading', 'locale' ), 'align' => 'center', 'level' => '2', ), ), array( 'core/paragraph', array( 'placeholder' => __( 'Add CTA text here', 'locale' ), 'align' => 'center', ), ), array( 'core/buttons', array( 'placeholder' => __( 'Add CTA buttons here', 'locale' ), 'align' => 'center', ), array( array( 'core/button', array( 'text' => __( 'Take action', 'locale' ), ), ), array( 'core/button', array( 'text' => __( 'Learn more', 'locale' ), ), ), ), ), ); // Echo out our JSX InnerBlocks compoennt for the editor. echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" template="' . esc_attr( wp_json_encode( $template ) ) . '" templateLock="false" />'; ?> </div> </div>
Mari kita pecahkan kode ini.
- Pada awalnya, kami memiliki boilerplate template blok generik yang disediakan ACF dalam panduan blok mereka, seperti dukungan untuk jangkar dan nama kelas khusus.
- Komponen InnerBlocks dapat menerima properti. Kami menggunakan tiga di template ini.
- Blok yang Diizinkan: Kami menambahkan serangkaian blok yang diizinkan untuk dikurasi. Hanya blok ini yang akan tersedia untuk dipilih di dalam ruang InnerBlocks blok khusus kami.
- Templat: Kita dapat meneruskan larik blok dan kita dapat meneruskan atribut blok untuk memulai blok saat pertama kali dimuat ke dalam editor.
- Perhatikan bahwa kita dapat meneruskan atribut blokir untuk menyiapkan pengguna agar berhasil. Judul sudah ditetapkan level 2, dan paragraf dipusatkan.
- Catatan: Blok inti akan selalu disebut dalam JavaScript sebagai {plugin}/blockname. Dalam kasus kami, kami menggunakan blok inti, tetapi jika Anda ingin menggunakan blok ACF khusus, Anda akan menulis 'acf' di depan nama blok. Ingat, saat menggunakan InnerBlocks, kami meneruskan komponen ini ke Editor WordPress, yang menggunakan React. Itu sebabnya kami berpikir di JS di sini.
- Catatan lain: perhatikan bahwa blok inti/tombol menggunakan InnerBlocks itu sendiri! Kami sebenarnya melewati array dari dua blok inti/tombol di dalamnya!
- Penguncian Template: templateLock diatur pada komponen InnerBlocks. Jika kami menyetelnya ke 'semua', tidak ada blok di templat kami yang disediakan untuk InnerBlocks yang dapat dipindahkan atau dihapus. Jika kita menyetelnya ke 'insert', blok di dalamnya hanya bisa dipindahkan, tidak ada blok yang bisa dihapus, dan tidak ada blok baru yang bisa ditambahkan. Jika kita menyetelnya ke 'false', instance InnerBlocks akan dibuka kuncinya dan akan dibuka kuncinya terlepas dari kunci templat induk mana pun (lebih lanjut tentang ini di bawah). Baca lebih lanjut tentang Blok Template di Buku Pegangan Editor Blok WordPress. Kami akan berbicara tentang penguncian blok lebih lanjut.
Kami memiliki blok baru! Setelah semua itu, dan beberapa gaya, tentu saja, blok contoh terlihat seperti ini di editor:
Nesting Deeper: Mengurasi Pengalaman Lebih Banyak lagi dengan Nested InnerBlocks
Kami memiliki blok yang bagus, dan kami tidak perlu menyiapkan WYSIWYG atau bahkan menangani bidang khusus di templat kami. Tetapi bagaimana jika kita ingin mengatur dan menyempurnakan pengalaman ini lebih jauh lagi untuk klien? Katakanlah kita mendapat permintaan untuk memastikan tajuk selalu ada, sehingga selalu ada blok tajuk, tetapi konten setelahnya fleksibel dan bahkan dapat menyertakan daftar atau jenis blok lainnya. Tujuan kami adalah untuk mencapai fleksibilitas itu, sekaligus menjaga konsistensi.
Mari pertimbangkan beberapa aturan saat bekerja dengan InnerBlocks:
- Satu blok hanya boleh memiliki satu instance InnerBlocks di dalamnya.
- Beberapa blok di dalam InnerBlocks dapat menggunakan komponen InnerBlocks mereka sendiri.
- InnerBlocks dapat dikunci melalui properti templateLock, tetapi instance InnerBlocks yang lebih dalam di dalam struktur blok bersarang dapat dibuka kuncinya lagi dengan menyetel templateLock ke false.
Salah satu solusinya adalah membuat blok baru yang berfungsi sebagai pembungkus InnerBlocks. Kami akan menyertakan blok itu di templat blok induk kami dan menguncinya, tetapi secara eksplisit membuka kunci blok pembungkus kami di dalamnya dengan menyetel 'templateLock' ke false. Kami juga mungkin ingin memastikan blok pembungkus khusus ini hanya tersedia di dalam blok induk yang kami pilih, dengan menyetel induk untuk blok kami. Kami dapat mengizinkan beberapa jenis blok dalam ruang itu untuk menawarkan daftar editor dan lebih banyak lagi, sambil tetap hanya mengizinkan tajuk, tombol, dan blok pembungkus kami di blok Ajakan Bertindak induk.
Penguncian Blok Individu
Fitur baru di WordPress 5.9 adalah kemampuan untuk mengunci masing-masing blok dalam sebuah template. Ini adalah solusi lain yang mungkin untuk masalah kami yang fleksibel namun konsisten.
Inilah tampilan template kita dengan beberapa blok individual terkunci:
<?php /** * ACF Call to Action example block template. * * More info: https://www.advancedcustomfields.com/resources/acf_register_block_type/ * * @param array $block The block settings and attributes. * @param string $content The block inner HTML (empty). * @param bool $is_preview True during AJAX preview. * @param (int|string) $post_id The post ID this block is saved to. * */ // Create id attribute allowing for custom "anchor" value. $block_ . $block['id']; if ( ! empty( $block['anchor'] ) ) { $block_id = $block['anchor']; } // Create class attribute allowing for custom "className" and "align" values. $class_name = 'acf-call-to-action-demo'; if ( ! empty( $block['className'] ) ) { $class_name .= ' ' . $block['className']; } if ( ! empty( $block['align'] ) ) { $class_name .= ' align' . $block['align']; } ?> <div class="<?php echo esc_html( $class_name ); ?>"> <div class="cta__inner"> <?php // Set up innerBlocks and provide a template. // Restrict InnerBlocks to allowed block list. $allowed_blocks = array( 'core/heading', 'core/paragraph', 'core/buttons' ); // Start InnerBlocks with a template. $template = array( array( 'core/heading', array( 'placeholder' => __( 'Heading', 'locale' ), 'align' => 'center', 'level' => '2', 'lock' => array( 'move' => true, // Block may nto be moved. 'remove' => true, // Block may not be removed. ), ), ), array( 'core/paragraph', array( 'placeholder' => __( 'Add CTA text here', 'locale' ), 'align' => 'center', ), ), array( 'core/buttons', array( 'placeholder' => __( 'Add CTA buttons here', 'locale' ), 'align' => 'center', 'lock' => array( 'move' => true, // Block may not be moved. 'remove' => true, // Block may not be removed. ), ), array( array( 'core/button', array( 'text' => __( 'Take action', 'locale' ), ), ), array( 'core/button', array( 'text' => __( 'Learn more', 'locale' ), ), ), ), ), ); // Echo out our JSX InnerBlocks compoennt for the editor. echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" template="' . esc_attr( wp_json_encode( $template ) ) . '" />'; ?> </div> </div>
Judul dan blok tombol seharusnya tidak lagi dapat dipindahkan atau dihapus. Pastikan untuk me-refresh editor, menghapus, dan kemudian menambahkan blok lagi untuk mendapatkan perubahan template.
Bonus: Membuat Blok yang Sama Secara Native
Setelah Anda memiliki proses build, membuat blok WordPress asli dengan React ternyata sangat mudah dan tidak terlalu berbeda dengan membuat template blok di php. Menyiapkan lingkungan pengembangan blok berada di luar cakupan artikel ini, tetapi ada sejumlah sumber daya untuk Anda mulai, seperti Buku Pegangan Editor Blok WordPress. Setelah Anda dapat menyertakan blok khusus, Anda dapat dengan cepat membuat blok menggunakan InnerBlocks.
Berikut ini adalah contoh blok Ajakan Bertindak kami index.js di React. Anda akan melihat strategi yang sama yang telah kita bahas di atas dengan ACF yang diterapkan di sini.
import { __ } from '@wordpress/i18n'; import { registerBlockType } from '@wordpress/blocks'; import { InnerBlocks } from '@wordpress/block-editor'; import { useBlockProps } from '@wordpress/block-editor'; /** * Block Name. * Create an example Call to Action Block * Uses InnerBlocks for editable content within. */ export const blockName = 'call-to-action'; /** * Block Config. * Set basic params for controlling the editor. */ export const BLOCK_CONFIG = { // Set up the block template. CTA_TEMPLATE: [ [ 'core/heading', { placeholder: __('CTA Headline', 'locale'), align: 'center', level: 2, lock: { move: true, remove: true, }, }, ], [ 'core/paragraph', { placeholder: 'Optional CTA text', align: 'center', lock: { move: true, }, }, ], [ 'core/buttons', { lock: { move: true, remove: true, }, className: 'is-content-justification-center', align: 'center', // __experimentalLayout - https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/buttons/block.json layout: { type: 'flex', justifyContent: 'center', }, }, [ [ 'core/button', { text: 'Apply now', lock: { move: true, remove: true, }, }, ], ['core/button', { text: 'Learn more' }], ], ], ], // Set up the allowed blocks. ALLOWED_BLOCKS: ['core/paragraph', 'core/heading', 'core/buttons'], }; // Register the block via WP func. Change 'myplugin' to your plugin or theme. registerBlockType(`myplugin/${blockName}`, { title: __('Call to Action', 'locale'), // Change 'locale' to your locale for internationalization. description: __( 'Call to action block with headline and buttons', 'locale' ), keywords: [__('call'), __('action'), __('cta')], category: 'design', supports: { anchor: true, defaultStylePicker: false, html: false, align: false, }, attributes: { anchor: { type: 'string', default: '', }, }, transforms: {}, variations: [], edit: (props) => { const blockProps = useBlockProps({ className: `wp-block-myplugin-${blockName}`, }); return ( <div {...blockProps}> <div className="cta__inner"> <div className="cta__inner-blocks-wrapper"> <InnerBlocks template={BLOCK_CONFIG.CTA_TEMPLATE} allowedBlocks={BLOCK_CONFIG.ALLOWED_BLOCKS} renderAppender={false} /> </div> </div> </div> ); }, save: () => { return ( <div> <div className="cta__inner"> <InnerBlocks.Content /> </div> </div> ); }, });
Maju dan bangun!
Sumber daya tambahan
- Artikel Bill Erickson di InnerBlocks
- Artikel Bill Erickson di Editor Blok
- Panduan Blok ACF
- Dokumentasi Jenis Blok Registrasi ACF
- Buku Pegangan Editor Blok WordPress
- Buku Pegangan Editor Blok WordPress: Membuat Tutorial Blok