Stwórz wspaniałe wrażenia z edycji WordPress i oszczędzaj czas dzięki Gutenberg InnerBlocks
Opublikowany: 2023-02-12Nie powtarzaj się
Dla programistów lenistwo może być zaletą. Dobrze wykonany komponent wielokrotnego użytku oszczędza czas i pozwala na wydajne ponowne użycie i spójność. To dobrze nadaje się do tworzenia doświadczeń edycyjnych w WordPress, ponieważ spójność rodzi znajomość i wiedzę dla osób korzystających z witryny na co dzień.
WordPress zrobił dużo hałasu wraz z wydaniem edytora bloków Gutenberga, znanego teraz po prostu jako „Edytor”. Do edycji, redagowania i publikowania treści zapewnia doskonałe wrażenia, znacznie lepsze niż starsze WYSIWYG. Jako programista chcę zapewnić moim klientom najlepsze wrażenia z edycji, chcę wykorzystać podstawową funkcjonalność i nie chcę wymyślać koła na nowo. Na szczęście WordPress pozwala nam robić to wszystko za pomocą niestandardowych bloków.
Wejdź do InnerBlocks
InnerBlocks to świetna funkcja w edytorze WordPress. Deweloperzy mogą używać podstawowych bloków, takich jak akapity, nagłówki i przyciski, aby stworzyć spójne środowisko dla klienta. Zamiast przepisywać sekcje tekstu i ponownie deklarować pola, klient otrzymuje doświadczenie, z którym się zapoznał; edytowanie i łączenie tych samych bloków. Przyjrzyjmy się blokowi, który być może będziemy musieli zbudować dla klienta, i zobaczmy, jak InnerBlocks może nam w tym pomóc.
Budowanie bloku za pomocą InnerBlocks
Przyjrzyjmy się temu blokowi i zastanówmy się, jak możemy go zbudować. Częstym narzędziem, po które sięgamy podczas tworzenia bloków, są Advanced Custom Fields (ACF). ACF Pro dodaje obsługę niestandardowych bloków, która pozwala programistom pisać bloki w PHP dla edytora i interfejsu użytkownika. Pozwala nam również korzystać z niestandardowych pól — paradygmatu znanego wielu programistom WordPress. ACF obsługuje InnerBlocks, co oznacza, że możemy utworzyć niestandardowy blok, ale nie będziemy nawet musieli pisać niestandardowego kodu dla tego nagłówka, akapitu lub przycisków.
Dzięki blokom ACF możemy wykorzystać podstawowe bloki, aby zapewnić doskonałe wrażenia podczas edycji całego tekstu, który widzimy w tym bloku. Inną potencjalną opcją byłoby użycie wzorców blokowych, ale jako programiści i kuratorzy fantastycznego doświadczenia WordPress, tworzenie niestandardowego bloku osiąga zamierzony cel.
Zablokuj kod rejestracyjny
Oto kod do zarejestrowania naszego niestandardowego bloku ACF. Przeczytaj więcej o korzystaniu z funkcji acf_register_block_type tutaj.
<?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. ), ) ); } );
Złammy kod. Używamy funkcji acf_register_block_type do zarejestrowania naszego bloku i przekazujemy tablicę argumentów, które definiują nasz blok oraz włączają i wyłączają funkcjonalność.
- Zauważ, że postępujemy zgodnie z zalecaną procedurą, aby dodać unikalną nazwę dla naszego bloku, a także czytelny dla człowieka tytuł i opis. Wskazujemy szablon renderowania, w którym później skonfigurujemy nasz szablon PHP dla bloku. Dodaliśmy również kategorię, w której chcemy, aby nasz blok był zgrupowany we Wstawiaczu bloków.
- Mamy przeszukiwalne słowa kluczowe, aby ułatwić wyszukiwanie bloku w module wstawiania.
- Dodaliśmy tablicę „obsługuje”, aby umożliwić takie funkcje, jak ustawianie kotwicy HTML, i wyłączyliśmy wyrównanie, ponieważ ten blok zawsze będzie znajdował się na środku strony.
- To obsługuje tablicę, w której włączamy magię InnerBlocks! Ustawienie „jsx” na true mówi ACF, że będziemy obsługiwać renderowanie szablonów React jsx wewnątrz naszego bloku.
Przejrzyjmy zawartość, której potrzebujemy w naszym bloku:
- Nagłówek
- Tekst akapitu
- Przyciski do działania!
Teraz normalnie przypisywalibyśmy pola do naszego bloku, jak opisano tutaj. Ale w tym przypadku nie musimy — możemy wykorzystać podstawowe bloki, aby osiągnąć to wszystko. Jeśli na przykład blok wymaga tła obrazu, dodanie pola obrazu ACF do bloku może być świetnym sposobem na osiągnięcie tego. Na razie jednak trzymajmy się naszego przykładu InnerBlocks i przejdźmy do szablonu.
Szablon bloku
Oto szablon nowego bloku. Upewnij się, że rejestracja bloku wskazuje lokalizację szablonu bloku. Powszechną praktyką jest umieszczanie ich w folderze częściowym w motywie.
<?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>
Złammy ten kod.
- Na początku mamy ogólny szablon szablonu bloku, który ACF zapewnia w swoich wytycznych blokowych, takich jak obsługa zakotwiczenia i niestandardowej nazwy klasy.
- Komponent InnerBlocks może odbierać właściwości. W tym szablonie używamy trzech.
- Dozwolone bloki: dodajemy tablicę dozwolonych bloków do wyboru. Tylko te bloki będą dostępne do wyboru w przestrzeni InnerBlocks naszego niestandardowego bloku.
- Szablon: możemy przekazać tablicę bloków i możemy przekazać atrybuty bloków, od których bloki będą zaczynać, gdy po raz pierwszy ładują się do edytora.
- Zauważ, że możemy przekazać atrybuty bloków, aby zapewnić naszym użytkownikom sukces. Nagłówek ma już ustawiony poziom 2, a akapit jest wyśrodkowany.
- Uwaga: podstawowe bloki będą zawsze określane w JavaScript jako {plugin}/blockname. W naszym przypadku używamy bloków podstawowych, ale gdybyś chciał użyć niestandardowego bloku ACF, napisałbyś „acf” przed nazwą bloku. Pamiętaj, że korzystając z InnerBlocks, przekazujemy ten komponent do edytora WordPress, który korzysta z React. Dlatego myślimy tutaj w JS.
- Kolejna uwaga: zauważ, że blok rdzenia/przycisków używa samego InnerBlocks! W rzeczywistości przekazujemy tablicę dwóch bloków rdzenia/przycisków!
- Blokowanie szablonu: templateLock jest ustawiony w komponencie InnerBlocks. Jeśli ustawimy to na „all”, żaden z bloków w naszym szablonie dostarczonym do InnerBlocks nie będzie mógł zostać przeniesiony ani usunięty. Jeśli ustawimy go na „wstaw”, znajdujące się w nim bloki będą mogły być tylko przesuwane, żadne bloki nie będą mogły być usuwane, ani dodawane nowe bloki. Jeśli ustawimy to na „false”, instancja InnerBlocks zostanie odblokowana i zostanie odblokowana niezależnie od jakichkolwiek blokad szablonów nadrzędnych (więcej na ten temat w dalszej części). Przeczytaj więcej o szablonach bloków w Podręczniku edytora bloków WordPress. Porozmawiamy więcej o blokowaniu bloków.
Mamy nowy blok! Po tym wszystkim i oczywiście odrobinie stylizacji przykładowy blok wygląda w edytorze tak:
Głębsze zagnieżdżanie: jeszcze większe ulepszanie doświadczenia dzięki Nested InnerBlocks
Mamy świetny blok i nie musieliśmy konfigurować WYSIWYG ani nawet obsługiwać niestandardowych pól w naszym szablonie. Ale co by było, gdybyśmy chcieli jeszcze bardziej dopracować i dopracować to doświadczenie dla klienta? Załóżmy, że otrzymujemy żądanie, aby upewnić się, że nagłówek jest zawsze obecny, więc zawsze istnieje blok nagłówka, ale treść po nim jest elastyczna i może nawet zawierać listę lub inny rodzaj bloku. Naszym celem jest osiągnięcie tej elastyczności przy jednoczesnym zachowaniu spójności.
Rozważmy kilka zasad podczas pracy z InnerBlocks:
- Pojedynczy blok może zawierać tylko jedną instancję InnerBlocks.
- Wiele bloków wewnątrz InnerBlocks może używać własnych komponentów InnerBlocks.
- InnerBlocks można zablokować za pomocą właściwości templateLock, ale instancje InnerBlocks znajdujące się głębiej w zagnieżdżonej strukturze bloku można ponownie odblokować, ustawiając templateLock na false.
Jednym z rozwiązań jest utworzenie nowego bloku, który służy jako opakowanie dla InnerBlocks. Umieścilibyśmy ten blok w naszym szablonie bloku nadrzędnego i zablokowalibyśmy go, ale jawnie odblokowalibyśmy nasz blok opakowujący wewnątrz, ustawiając „templateLock” na false. Możemy również chcieć upewnić się, że ten specjalny blok opakowujący jest dostępny tylko w wybranym przez nas bloku nadrzędnym, ustawiając rodzica dla naszego bloku. Moglibyśmy zezwolić wielu typom bloków w tej przestrzeni na oferowanie list redaktorów i nie tylko, jednocześnie zezwalając tylko na nagłówek, przyciski i nasz blok opakowujący w nadrzędnym bloku wezwania do działania.
Indywidualne blokowanie bloków
Nowością w WordPress 5.9 jest możliwość blokowania poszczególnych bloków w szablonie. Jest to kolejne możliwe rozwiązanie naszego elastycznego, ale spójnego problemu.
Oto jak wygląda nasz szablon z zablokowanymi pojedynczymi blokami:
<?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>
Nagłówek i bloki przycisków nie powinny już być przenoszone ani usuwane. Pamiętaj, aby odświeżyć edytor, usunąć, a następnie ponownie dodać blok, aby uzyskać zmiany szablonów.
Bonus: tworzenie tego samego bloku natywnie
Gdy masz już proces kompilacji, tworzenie natywnych bloków WordPressa za pomocą React jest zaskakująco łatwe i nie różni się zbytnio od tworzenia szablonów bloku w php. Konfigurowanie blokowego środowiska programistycznego wykracza poza zakres tego artykułu, ale istnieje wiele zasobów ułatwiających rozpoczęcie pracy, takich jak Podręcznik edytora bloków WordPress. Gdy będziesz w stanie dołączyć niestandardowe bloki, możesz szybko budować bloki za pomocą InnerBlocks.
Oto przykład naszego bloku wezwań do działania index.js w React. Zobaczysz tę samą strategię, którą omówiliśmy powyżej z zastosowanym tutaj ACF.
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> ); }, });
Idź i buduj!
Dodatkowe zasoby
- Artykuł Billa Ericksona na temat InnerBlocks
- Artykuły Billa Ericksona na temat edytora bloków
- Przewodnik po blokach ACF
- Dokumentacja typu bloku rejestru ACF
- Podręcznik edytora bloków WordPress
- Podręcznik edytora bloków WordPress: Utwórz samouczek dotyczący bloków