Mange mennesker klager over de forhindringer, der er forbundet med at komme i gang med at bygge Gutenberg-blokke og -apps. Indlæringskurven er stejl, primært på grund af vanskeligheden ved at installere og konfigurere udviklingsmiljøet. Derudover er et solidt kendskab til JavaScript, Node.js, React og Redux uundværlige ingredienser til denne ret komplekse opskrift.

Den officielle WordPress Block Editor Handbook giver udviklere en enorm mængde oplysninger, men du kan finde dig selv fortabt i dette hav af detaljer.

Og det er værd at nævne, hvad Matías Ventura, ledende arkitekt for Gutenberg-projektet, rapporterede i sit interview med WP Tavern:

Selv om der er folk, der kan lære det hurtigt, er det stadig en stor barriere for folk. Jeg tror, der er flere lag i dette; dokumentationen kunne være en størrelsesorden bedre i både organisation og præsentation. Jeg håber, at vi kan gøre meget mere på dette område.

Med det i tankerne har vi besluttet at give en trinvis vejledning, der har til formål at hjælpe vores læsere med at komme i gang med udvikling af Gutenberg-blokke.

Lyder det interessant? Lad os dykke ned i det!

Forudsætninger for udvikling af Gutenberg-blokke

Til denne tutorial er de eneste nødvendige færdigheder et godt kendskab til udvikling af WordPress-plugins og mindst en grundlæggende forståelse af HTML, CSS, JavaScript og React.

Bliver dette et ambitiøst projekt? Det kan du bande på, at det vil være!

Det var ikke let at finde det rette kompromis mellem fuldstændighed og enkelhed eller at beslutte, hvilke emner der skulle medtages og hvilke der skulle udelades.

Forhåbentlig vil mellemliggende og avancerede læsere tilgive, at vi ikke dykker dybt ned i visse koncepter som React state, Redux store, high order components osv. Disse emner kræver ekstra plads og opmærksomhed og er sandsynligvis for avancerede for begyndende blokudvikling (medmindre du er React-udvikler).

Af samme grund vil vi ikke dække nogle af de mere avancerede emner i forbindelse med udvikling af Gutenberg-blokke, såsom dynamiske blokke og metabokse.

Med den viden, du får når vi når enden af denne artikel, vil du kunne begynde at have det sjovt og være produktiv med det samme.

Når du først er kommet i gang med blokbygning, vil du være klar til at forbedre dine færdigheder yderligere og bygge endnu mere avancerede Gutenberg-blokke på egen hånd.

Hvad er en Gutenberg-blok?

Siden den blev frigivet første gang i december 2018 er blokredigeringsprogrammet blevet kraftigt forbedret i alle aspekter: mere kraftfulde API’er, en mere avanceret brugergrænseflade, forbedret brugervenlighed, et ton af nye blokke, de første implementeringer af Full Site Editing og meget mere.

Kort sagt, selv om Gutenberg stadig er under kraftig udvikling, er det kommet langt — og i dag er blokeditoren en fuldgyldig kandidat som en pålidelig, funktionel website builder.

Set fra en udviklers synspunkt er Gutenberg en React-baseret Single Page Application (SPA), der giver WordPress-brugere mulighed for at oprette, redigere og slette indhold i WordPress. Dette bør dog ikke få dig til at tænke på en forbedret version af den traditionelle indholdseditor.

Vi ønsker at gøre dette klart:

I Gutenberg er indholdet opdelt i blokke, som er “mursten”, som brugerne kan bruge til at oprette indlæg og sider eller hele deres websites.

Men hvad er en blok teknisk set?

Vi kan godt lide WordPress’ definition:

“Blok” er den abstrakte betegnelse, der bruges til at beskrive enheder af markup, som, sammensat sammen, udgør indholdet eller layoutet af en webside. Ideen kombinerer koncepter af det, som vi i WordPress i dag opnår med shortcodes, tilpasset HTML og embed discovery, i et enkelt konsistent API og en enkelt brugeroplevelse.

Titler, afsnit, kolonner, billeder, gallerier og alle de elementer, der udgør editorens brugerflade, fra sidebarpaneler til kontrolelementer i blokværktøjslinjen, er React-komponenter.

Så hvad er React-komponenter? W3Schools giver følgende definition:

Komponenter er uafhængige og genanvendelige kodestykker. De tjener det samme formål som JavaScript-funktioner, men arbejder isoleret og returnerer HTML via en render() -funktion.

Arbejde med Gutenberg-blokke i WordPress 5.8.
Arbejde med Gutenberg-blokke i WordPress 5.8.

Mens den redigeringsoplevelse, der leveres af Gutenberg, er ny i forhold til den klassiske WordPress-editor, ændres den måde, WordPress gemmer dine stykker indhold i databasen, på ingen måde. Det skyldes, at Gutenberg er et program, der fungerer i WordPress, men som ikke ændrer den måde, CMS’et fungerer på i sin kerne.

Indlæg (og det omfatter indlæg, sider og brugerdefinerede indlægstyper), der oprettes med Gutenberg, gemmes stadig i tabellen wp_posts, præcis som med den klassiske editor.

Men i et indlæg oprettet med Gutenberg finder du yderligere bider af information i tabellen, som repræsenterer en grundlæggende forskel mellem indlæg oprettet via den klassiske editor vs. Gutenberg.

Disse stykker information ligner HTML-kommentarer, og de har en specifik funktion: afgrænsning af blokke:

Et blogindlæg i koderedigeringsvisning.
Et blogindlæg i Code editor view.

Blokafgrænsere fortæller WordPress, hvilken blok der skal gengives på skærmen. De giver også værdier for blokegenskaber i et JSON-objekt. Disse rekvisitter dikterer den måde, som blokken skal gengives på skærmen:

Et blogindlæg gemt i wp_posts-tabel.
Et blogindlæg gemt i tabellen wp_posts.

Opsætning af dit WordPress-udviklingsmiljø

Opsætning af et moderne JavaScript-udviklingsmiljø kræver et solidt kendskab til avancerede teknologier som Webpack, React og JSX, Babel, ESLint osv.

Skræmt? Det skal du ikke være! WordPress-fællesskabet er allerede kommet til undsætning ved at levere kraftfulde værktøjer, der lader dig undgå en rodet manuel konfigurationsproces.

For at holde tingene enkle vil vi ikke dække transpiling i denne artikel (som vi dog anbefaler, at du gør dig bekendt med, når du har lært det grundlæggende i blokudvikling). I stedet vil vi præsentere to alternative værktøjer, som du kan bruge til hurtigt og nemt at opsætte et moderne JavaScript-udviklingsmiljø på få minutter. Det er op til dig at vælge det, du finder mest praktisk for dit projekt.

Opsætning af et JavaScript-udviklingsmiljø til at bygge Gutenberg-blokke er en proces i tre trin:

  1. Installer Node.js og npm
  2. Opsætning af udviklingsmiljøet
  3. Opsæt blokpluginet

Lad os komme i gang.

1. Installer Node.js og npm

Før du installerer dit udviklingsmiljø og registrerer din første blok, skal du installere Node.js og Node-pakkehåndteringsprogrammet (npm).

.

Du kan installere Node.js og npmflere forskellige måder. Men først vil du måske tjekke, om softwaren allerede er installeret på din maskine.

For at gøre dette skal du starte terminalen og køre følgende kommando:

node -v

Hvis resultatet er command not found, er Node.js ikke installeret på din computer, og du kan fortsætte med installationen.

I denne artikel har vi valgt den nemmeste installationsmulighed, som er Node Installer. Det eneste, du skal gøre, er at downloade den version, der svarer til dit operativsystem, og starte installationsguiden:

Node.js Downloadside.
Node.js Downloads side.

Når du har installeret Node.js, skal du køre kommandoen node -v i din terminal igen. Du kan også køre kommandoen npm -v for at bekræfte, at du har npm-pakken tilgængelig.

Du er nu udstyret med følgende værktøjer:

  • npx Node.js-pakkeløberen Node.js. Dette giver dig mulighed for at køre en npm -kommando uden at installere den først.
  • Node.js-pakkehåndteringsprogrammet npm Node.js (se dokumentationen). Denne bruges til at installere afhængigheder og køre scripts.

Det næste skridt er at installere udviklingsmiljøet.

2. Opsætning af dit udviklingsmiljø

Når du har de nyeste versioner af Node.js og npm på din lokale maskine, har du brug for et udviklingsmiljø til WordPress.

Du kan enten bruge et lokalt udviklingsmiljø som DevKinsta eller bruge det officielle WordPress-værktøj. Lad os tage et kig på begge muligheder.

Mulighed 1: Lokalt udviklingsmiljø (DevKinsta)

Med få klik kan du installere WordPress lokalt ved hjælp af DevKinsta, vores moderne lokale WordPress-udviklingsværktøj, med få klik. Eller du kan vælge et andet lokalt udviklingsværktøj, som f.eks. MAMP eller XAMPP:

Opret et nyt WordPress-websted i DevKinsta.
Opret et nyt WordPress-websted i DevKinsta.

Mulighed 2: wp-env

Du kan også vælge det officielle værktøjwp-env, som giver et lokalt WordPress-dev-miljø, som du kan starte direkte fra kommandolinjen. Noah Alen definerer det som følgende:

Lokale WordPress-miljøer er nu lige så enkle som at køre en enkelt kommando. wp-env er et nulkonfigurationsværktøj til smertefrie lokale WordPress-miljøer. Det giver beslutninger over indstillinger, så brugerne hurtigt kan spinne WordPress op uden at spilde tid. Målet er nemlig at gøre disse miljøer let tilgængelige for alle – uanset om du er udvikler, designer, leder eller andet.

Hvis du beslutter dig for at give det et forsøg, kræver installation af wp-env en minimal indsats. Du skal blot følge disse trin:

Trin 1: Bekræft installation af Docker og Node.js

For at opfylde de tekniske krav skal du først have både Docker og Node.js installeret på din computer. Det skyldes, at wp-env opretter en Docker-instans, der kører et WordPress-websted. Alle ændringer, der foretages i koden, afspejles straks i WordPress-instansen.

Trin 2: Installer @wordpress/env fra kommandolinjen

Når Docker og Node.js kører på din computer, kan du gå videre og installere WordPress-udviklingsmiljøet.

Du kan installere wp-env enten globalt eller lokalt. Hvis du vil gøre det globalt, skal du køre følgende kommando fra plugins-mappen (mere om dette i boksen “Vigtigt” nedenfor):

npm install -g @wordpress/env

Lad os bryde det ned:

For at bekræfte, at wp-env er blevet installeret med succes, skal du køre følgende kommando:

wp-env --version

Du bør se den aktuelle wp-env -version, hvilket betyder, at du nu kan starte miljøet ved hjælp af følgende kommando fra din plugin-mappe:

wp-env start

Du kan få adgang til WordPress-dashboardet ved hjælp af følgende adresse:

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

Standardoplysningerne er som følger:

  • Brugernavn: admin
  • Adgangskode: password

Opsætning af dit blokeringsplugin

Nu har du brug for et startblok-plugin til at bygge videre på. Men i stedet for manuelt at oprette et udviklingsblok-plugin med alle nødvendige filer og mapper kan du blot køre et dev-tool, der leverer alle de filer og konfigurationer, du har brug for for at komme i gang med blokudvikling.

Igen har du et par muligheder at vælge imellem. Lad os tage et kig på hver enkelt.

Mulighed 1: Opsætning af et blokplugin med @wordpress/create-block

@wordpress/create-block er det officielle nulkonfigurationsværktøj til oprettelse af Gutenberg-blokke:

Create Block er en officielt understøttet måde at oprette blokke på for at registrere en blok til et WordPress-plugin. Det tilbyder en moderne opbygning opsætning uden konfiguration. Det genererer PHP-, JS- og CSS-kode og alt andet, du har brug for til at starte projektet.

Den er i høj grad inspireret af create-react-app. Stor ros til @gaearon, hele Facebook-holdet og React-fællesskabet.

Når dit lokale miljø er oppe at køre, kan du oprette en startblok ved blot at køre kommandoen npx @wordpress/create-block, og den vil levere alle de filer og mapper, du har brug for til at oprette plugin-stilladset og registrere en ny blok.

Lad os køre en test for at se, hvordan det fungerer.

Fra dit kommandolinjeværktøj skal du navigere til mappen /wp-content/plugins/ og køre følgende kommando:

npx @wordpress/create-block my-first-block

Når du bliver bedt om at bekræfte, skal du indtaste y for at fortsætte:

Oprettelse af en blok med @wordpress/create-block.
Oprettelse af en blok med @wordpress/create-block.

Processen tager et lidt tid. Når den er færdig, bør du få følgende svar:

Block plugin er blevet oprettet.
Block plugin er blevet oprettet.

Og det var det!

Start nu dit WordPress-udviklingsmiljø og gå til skærmen Plugins i WordPress-dashboardet. Et nyt plugin ved navn “My First Block” skulle være blevet tilføjet til din plugin-liste:

Block-plugin'et er blevet installeret med succes.
Block-pluginet er blevet installeret med succes.

Aktivér pluginet om nødvendigt, opret et nyt blogindlæg, rul ned i blokindsatsen til sektionen Widgets, og vælg din nye blok:

En eksempelblok oprettet med @wordpress/create-block.
En eksempelblok oprettet med @wordpress/create-block.

Gå nu tilbage til terminalen og ændre den aktuelle mappe til my-first-block:

cd my-first-block

Kør derefter følgende kommando:

npm start

Dette giver dig mulighed for at køre pluginet i udviklingstilstand. Hvis du vil oprette produktionskoden, skal du bruge følgende kommando:

npm run build

Mulighed 2: Opsætning af et blokplugin med create-guten-block

create-guten-block er et udviklingsværktøj fra en tredjepart til at bygge Gutenberg-blokke:

create-guten-block is zero configuration dev-toolkit (#0CJS) til at udvikle WordPress Gutenberg-blokke på få minutter uden at konfigurere React, webpack, ES6/7/8/Next, ESLint, Babel osv.

Ligesom det officielle værktøj create-block er create-guten-block baseret på create-react-app og kan hjælpe dig med at generere dit første blokplugin uden besvær.

Værktøjssættet indeholder alt, hvad du har brug for til at oprette et moderne WordPress-plugin, herunder følgende:

  • React, JSX og ES6-syntaksunderstøttelse.
  • webpack dev/produktions build proces bag scenen.
  • Sproglige ekstramateriale ud over ES6 som f.eks. objektspredningsoperatoren.
  • CSS med automatisk præfikseret CSS, så du ikke behøver -webkit eller andre præfikser.
  • Et build-script til at bundle JS, CSS og billeder til produktion med source-maps.
  • Problemløse opdateringer til ovenstående værktøjer med en enkelt afhængighed cgb-scripts.

Bemærk følgende advarsel:

Kompromiset er, at disse værktøjer er forudkonfigureret til at fungere på en bestemt måde. Hvis dit projekt har brug for mere tilpasning, kan du “skubbe” det ud og tilpasse det, men så skal du vedligeholde denne konfiguration.

Når du har et lokalt WordPress-websted ved hånden, skal du starte dit kommandolinjeværktøj, navigere til mappen /wp-content/plugins i din installation og køre følgende kommando:

npx create-guten-block my-first-block

Du skal vente et minut eller to, mens projektstrukturen oprettes og afhængighederne downloades:

Oprettelse af en Gutenberg-blok med create-guten-block.
Oprettelse af en Gutenberg-blok med create-guten-block.

Når processen er afsluttet, bør du se følgende skærm:

Gutenberg-blok oprettet med succes med create-guten-block.
Gutenberg-blok oprettet med succes med create-guten-block.

Det næste billede viser projektstrukturen med terminalen, der kører i Visual Studio Code:

Block-plugin i Visual Studio Code:
Block-plugin i Visual Studio Code:

Gå nu tilbage til dit WordPress-dashboard. Et nyt element bør være opført på skærmen Plugins — det er my-first-block pluginet:

Skærmbilledet Plugins med et nyt plugin oprettet med create-guten-block.
Skærmbilledet Plugins med et nyt plugin oprettet med create-guten-block.

Aktivér pluginet og gå tilbage til terminalen. Skift den aktuelle mappe til my-first-block, og kør derefter npm start:

cd my-first-block
npm start

Du bør få følgende svar:

npm started.
npm started.

Igen giver dette dig mulighed for at køre plugin’et i udviklingstilstand. For at oprette produktionskoden skal du bruge:

npm run build

Aktivér pluginet og opret et nyt indlæg eller en ny side, gennemse derefter dine blokke og vælg din helt nye Gutenberg-blok:

En ny blok oprettet med create-guten-block.
En ny blok oprettet med create-guten-block.

For en mere dybdegående oversigt eller i tilfælde af fejl kan du se dokumentationen fra Ahmad Awais.

En gennemgang af Starter Block Scaffolding

Uanset hvilket af de to dev-tools — create-block eller create-guten-block — du vælger, har du nu et block-stillads, som du kan bruge som udgangspunkt for at bygge et block-plugin.

Men hvad er block scaffolding egentlig?

Block scaffolding er et kortfattet udtryk, der beskriver den understøttende mappestruktur, du har brug for, for at WordPress kan genkende en blok. Typisk indeholder denne mappe filer som index.php, index.js, style.css og andre – som igen indeholder kald som register_block_type.

Vi valgte det officielle Create Block dev-tool, da det bruges i Block Editor Handbook. Men selv hvis du vælger at gå med et tredjepartsværktøj som create-guten-block, vil din oplevelse ikke være alt for anderledes.

Når det er sagt, så lad os dykke dybere ned i create-block -værktøjet.

Et nærmere kig på Create Block Dev-værktøjet

Som vi nævnte ovenfor, er Create Block det officielle kommandolinjeværktøj til at oprette Gutenberg-blokke. Ved at køre @wordpress/create-block i din terminal genereres de PHP-, JS- og SCSS-filer og den kode, der er nødvendig for at registrere en ny bloktype:

npx @wordpress/create-block [options] [slug]
  • [slug] (valgfrit) — bruges til at tildele blok-sluggen og installere pluginet
  • [options] (valgfrit) — tilgængelige indstillinger

Som standard er der tildelt en ESNext-skabelon. Det betyder, at du får den næste version af JavaScript med tilføjelsen af JSX-syntaksen.

Hvis du udelader bloknavnet, kører kommandoen i interaktiv tilstand, så du kan tilpasse flere indstillinger, inden filerne genereres:

npx @wordpress/create-block
Kører Create Block i interaktiv tilstand
Kører Create Block i interaktiv tilstand

Billedet nedenfor viser filstrukturen for et blokplugin, der er oprettet med det officielle Create Block-værktøj:

Filer og mapper i et blok-plugin oprettet med @wordpress/create-block.
Filer og mapper i et blok-plugin oprettet med @wordpress/create-block.

Når det er sagt, lad os gennemgå de vigtigste filer og mapper i vores nye block plugin.

Plugin-filen

Med den vigtigste plugin-fil registrerer du blokken på serveren:

<?php
/**
 * Plugin Name:       Kinsta Academy Block
 * Plugin URI:        https://kinsta.com/
 * Description:       An example block for Kinsta Academy students
 * Requires at least: 5.9
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            Kinsta Students
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       ka-example-block
 *
 * @package           ka-example-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/reference/functions/register_block_type/
 */
function ka_example_block_ka_example_block_block_init() {
	register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'ka_example_block_ka_example_block_block_init' );

Funktionen register_block_type registrerer en bloktype på serveren ved hjælp af de metadata, der er gemt i block.json-filen.

Funktionen tager to parametre:

  • Navnet på bloktypen, herunder namespace, eller en sti til den mappe, hvor block.json-filen er placeret, eller et fuldstændigt WP_Block_Type -objekt
  • Et array af bloktypeargumenter

I ovenstående kode returnerer den magiske konstant __DIR__ den aktuelle mappe. Det betyder, at filen block.json befinder sig i undermappen /build.

Filen package.json

I filen package.json defineres JavaScript-egenskaber og scripts for dit projekt. Det er her, du kan installere dine projektafhængigheder.

For bedre at forstå, hvad denne fil er beregnet til, skal du åbne den med din foretrukne kodeeditor:

{
	"name": "ka-example-block",
	"version": "0.1.0",
	"description": "An example block for Kinsta Academy students",
	"author": "Kinsta Students",
	"license": "GPL-2.0-or-later",
	"homepage": "https://kinsta.com/",
	"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",
		"packages-update": "wp-scripts packages-update",
		"plugin-zip": "wp-scripts plugin-zip",
		"start": "wp-scripts start"
	},
	"devDependencies": {
		"@wordpress/scripts": "^24.1.0"
	},
	"dependencies": {
		"classnames": "^2.3.2"
	}
}

Ejendommen scripts er en ordbog, der indeholder kommandoer, som køres på forskellige tidspunkter i en pakkes livscyklus ved hjælp af npm run [cmd].

I denne artikel vil vi bruge følgende kommandoer:

  • npm run build — oprette et (komprimeret) produktionsbyggeri
  • npm run start eller npm start — opretter et (ukomprimeret) udviklingsbyggeri

dependencies og devDependencies er to objekter, der mapper et pakkenavn til en version. dependencies er påkrævet i produktion, mens devDependences kun er påkrævet til lokal udvikling (læs mere).

Den eneste standard dev-afhængighed er pakken @wordpress/scripts, som er defineret som “en samling af genanvendelige scripts skræddersyet til WordPress-udvikling.”

Filen block.json

Fra WordPress 5.8 er metadatafilen block.json den kanoniske måde at registrere bloktyper på.

At have en block.json-fil giver flere fordele, herunder forbedret ydeevne og bedre synlighed i WordPress Plugins-kataloget:

Fra et ydelsesperspektiv vil blokke, der er registreret med block.json, få optimeret deres asset enqueuing ud af boksen, når temaer understøtter lazy loading-aktiver, når de er registreret med block.json. De CSS- og JavaScript-aktiver på frontend, der er anført i egenskaberne style eller script, vil kun blive sat i kø, når blokken er til stede på siden, hvilket resulterer i reducerede sidestørrelser.

Kørsel af kommandoen @wordpress/create-block genererer følgende block.json-fil:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "ka-example-block/ka-example-block",
	"version": "0.1.0",
	"title": "Kinsta Academy Block",
	"category": "widgets",
	"icon": "superhero-alt",
	"description": "An example block for Kinsta Academy students",
	"supports": {
		"html": false
	},
	"textdomain": "ka-example-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Her er den fulde liste over standardegenskaber:

  • apiVersion — den version af API’en, som blokken anvender (den nuværende version er 2)
  • name — en unik identifikator for en blok, herunder et navnespace
  • version — den aktuelle version af en blok
  • title — en visningstitel for en blok
  • category — en blokkategori
  • icon — en Dashicon-slug eller et brugerdefineret SVG-ikon
  • description — en kort beskrivelse, der er synlig i blokinspektøren
  • supports — et sæt indstillinger til at styre de funktioner, der anvendes i editoren
  • textdomain — plugin-tekstdomænet
  • editorScript — definitionen af editor-scriptet
  • editorStyle — definition af editor-stil
  • style — giver alternative stilarter for en blok

Ud over de egenskaber, der er anført ovenfor, kan du (og vil sandsynligvis) definere et attributes -objekt, der indeholder oplysninger om data, der er gemt i din blok. I din block.json kan du angive et vilkårligt antal attributter i nøgle/værdi-par, hvor nøglen er attributnavnet og værdien er attributdefinitionen.

Tag et kig på følgende eksempel på attributdefinitioner:

"attributes": {
	"content": {
		"type": "array",
		"source": "children",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"link": { 
		"type": "string", 
		"default": "https://kinsta.com" 
	}
},

Vi vil dykke dybere ned i block.json-filen senere i artiklen, men du kan også tjekke Block Editor Handbook for mere detaljerede oplysninger om block.json metadata og attributter.

Mappen src

Det er i mappen src, at udviklingen foregår. I den mappe finder du følgende filer:

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

index.js

Filen index.js er dit udgangspunkt. Her skal du importere afhængigheder og registrere bloktypen på klienten:

import { registerBlockType } from '@wordpress/blocks';

import './style.scss';

import Edit from './edit';
import save from './save';
import metadata from './block.json';

registerBlockType( metadata.name, {
	/**
	 * @see ./edit.js
	 */
	edit: Edit,

	/**
	 * @see ./save.js
	 */
	save,
} );

Den første erklæring importerer funktionen registerBlockType fra pakken @wordpress/blocks. De følgende importstatements importerer stylesheetet sammen med funktionerne Edit og save og et metadataobjekt fra filen block.json.

Funktionen registerBlockType registrerer komponenten på klienten. Funktionen tager to parametre: et bloknavn og et blokkonfigurationsobjekt.

Funktionen Edit giver blokgrænsefladen som gengivet i blokeditoren, mens funktionen save giver den struktur, der vil blive serialiseret og gemt i databasen (læs mere).

edit.js

edit.js er det sted, hvor du skal bygge blokadministrationsgrænsefladen:

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>
	);
}

Først importeres __ -funktionen fra @wordpress/i18n -pakken (denne pakke indeholder en JavaScript-version af oversættelsesfunktionerne), den useBlockProps React hook, og filen editor.scss.

Derefter eksporterer den React-komponenten (læs mere om import- og eksportangivelser ).

save.js

I filen save.js opbygger vi blokstrukturen, som skal gemmes i databasen:

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 og style.scss

Ud over scripts findes der to SASS-filer i src-mapperne. Filen editor.scss indeholder de stilarter, der anvendes på blokken i editorens kontekst, mens filen style.scss indeholder blokens stilarter til visning i frontend såvel som i editoren. Vi dykker dybere ned i disse filer i anden del af denne vejledning.

Node_modules og build-mapperne

Mappen node_modules indeholder node-moduler og deres afhængigheder. Vi vil ikke dykke dybere ned i nodepakker, da det ligger uden for denne artikels rækkevidde, men du kan læse mere i denne artikel om, hvor npm installerer pakkerne.

Mappen build indeholder de JS- og CSS-filer, der er resultatet af byggeprocessen. Du kan dykke dybere ned i byggeprocessen i vejledningerne ESNext-syntaks og JavaScript Build Setup.

Projektet: Bygning af din første Gutenberg-blok

Det er tid til at få fingrene i maskineriet. Dette afsnit vil lære dig, hvordan du opretter et plugin, der leverer en CTA-blok ved navn Kinsta Academy Block.

Blokken vil bestå af to kolonner, med et billede til venstre og et tekstafsnit til højre. En knap med et tilpasningsbart link vil blive placeret under teksten:

Blokketypen, som du lærer at bygge i denne vejledning.
Blokketypen, som du lærer at bygge i denne vejledning.

Dette er blot et simpelt eksempel, men det giver os mulighed for at dække det grundlæggende i Gutenberg-blokudvikling. Når du har fået en klar forståelse af det grundlæggende, kan du gå videre og skabe flere og mere komplekse Gutenberg-blokke ved hjælp af Block Editor Handbook og andre af de store ressourcer, der er tilgængelige derude.

Hvis vi antager, at du har den nyeste version af WordPress kørende på dit lokale udviklingsmiljø, er det her, hvad du skal lære fra nu af:

Klar… parat… start!

Sådan opsættes startblok pluginet

Start dit kommandolinjeværktøj, og naviger til mappen /wp-content/plugins:

Ny terminal i mappen i Mac OS.
Ny terminal i mappen i Mac OS.

Nu skal du køre følgende kommando:

npx @wordpress/create-block

Denne kommando genererer PHP-, SCSS- og JS-filerne til registrering af en blok i interaktiv tilstand, så du nemt kan tilføje de nødvendige data til din blok. I vores eksempel bruger vi følgende oplysninger:

  • Skabelonvariant: statisk
  • Blok-slug: ka-example-block
  • Internt navnerum: ka-example-block
  • Visningstitel for blok: Kinsta Academy Block: Kinsta Academy Block
  • Kort beskrivelse af blokken: Kinsta Kinsta En eksempelblok for Kinsta Academy-studerende
  • Dashicon: superhero-alt
  • Kategori navn: widgets
  • Ønsker du at tilpasse WordPress-pluginet?: ja
  • Hjemmesiden for pluginet: https://kinsta.com/
  • Nuværende plugin-version: 0.1.0
  • Plugin-forfatter: dit navn
  • Licens: –
  • Link til licensteksten: –
  • Brugerdefineret domænesti til oversættelser: –

Det tager et par minutter at installere pluginet og alle afhængigheder. Når processen er afsluttet, får du følgende svar:

Eksempelblokken er blevet installeret og registreret til udvikling.
Eksempelblokken er blevet installeret og registreret til udvikling.

Nu skal du køre følgende kommando fra mappen /wp-content/plugins:

cd ka-example-block
Kørsel af kommandoer fra Visual Studio Code Terminal.
Kørsel af kommandoer fra Visual Studio Code Terminal.

Endelig kan du fra din plugin-mappe (ka-example-block i vores eksempel) starte udviklingen med:

npm start

Åbn nu skærmen Plugins for at finde og aktivere Kinsta Academy Block-plugin:

Aktivér eksempelblokken
Aktivér eksempelblokken

Opret et nyt indlæg, åbn blokindsætteren, og rul ned til kategorien Design. Klik for at tilføje Kinsta Academy-blokken:

En startblok bygget med @wordpress/create-block.
En startblok bygget med @wordpress/create-block.

block.json på arbejde

Som vi nævnte tidligere, finder den server-side blokregistrering sted i hovedfilen .php. Vi vil dog ikke definere indstillinger i .php-filen. I stedet vil vi bruge block.json-filen.

Så åbn block.json igen, og se nærmere på standardindstillingerne:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "ka-example-block/ka-example-block",
	"version": "0.1.0",
	"title": "Kinsta Academy Block",
	"category": "widgets",
	"icon": "superhero-alt",
	"description": "An example block for Kinsta Academy students",
	"supports": {
		"html": false
	},
	"textdomain": "ka-example-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Scripts og stilarter

editorScript, editorStyle og style giver de relative stier til frontend- og backend-scripts og -stilarter.

Du behøver ikke manuelt at registrere de scripts og stilarter, der er defineret her, fordi de automatisk registreres og indkøges af WordPress. For at bevise det skal du starte browserinspektøren og åbne fanen Netværk:

Inspektion af ressourcer i Chrome DevTools.
Inspektion af ressourcer i Chrome DevTools.

Som du kan se på billedet ovenfor, er vores index.js-script, der befinder sig i build-mappen, regelmæssigt blevet sat i kø uden at skulle tilføje nogen PHP-kode.

UI-etiketter

Egenskaberne title og description giver de etiketter, der er nødvendige for at identificere blokken i editoren:

Bloknavn og -beskrivelse i bloksidebaren.
Bloknavn og -beskrivelse i bloksidebaren.

Keywords

Som vi nævnte tidligere, kan du konfigurere dine blokindstillinger præcist ved hjælp af egenskaber og attributter. Du kan f.eks. tilføje en eller flere keywords for at hjælpe brugerne med at søge efter blokke:

"keywords": [ 
		"kinsta", 
		"academy", 
		"superhero" 
	],

Hvis du nu indtaster “kinsta”, “academy” eller “superhero” i quick inserter, vil redaktøren foreslå dig Kinsta Academy-blokken:

Søgning efter en blok ved hjælp af et nøgleord i den hurtige indsætter.
Søgning efter en blok ved hjælp af et nøgleord i den hurtige indsætter.

Lokalisering

Hvis du undrer dig over, hvordan lokaliseringen af strengene i JSON-filen sker, er svaret her:

I JavaScript kan du bruge metoden now registerBlockTypeFromMetadata fra @wordpress/blocks -pakken til at registrere en bloktype ved hjælp af de metadata, der er indlæst fra block.json-filen. Alle lokaliserede egenskaber bliver automatisk pakket ind i _x (fra @wordpress/i18n pakken) funktionsopkald svarende til hvordan det fungerer i PHP med register_block_type_from_metadata. Det eneste krav er at indstille textdomain -egenskaben i block.json-filen.

Her bruger vi funktionen registerBlockType i stedet for registerBlockTypeFromMetadata, da sidstnævnte er blevet deprecated siden Gutenberg 10.7, men mekanismen er den samme.

Brug af indbyggede komponenter: RichText-komponenten

De elementer, der udgør en Gutenberg-blok, er React-komponenter, og du kan få adgang til disse komponenter via den globale variabel wp. Prøv f.eks. at skrive wp.editor i din browsers konsol. Dette vil give dig den fulde liste over de komponenter, der er inkluderet i modulet wp.editor.

Rul gennem listen, og gæt, hvad komponenterne er beregnet til ud fra deres navne.

På samme måde kan du tjekke listen over komponenter, der indgår i modulet wp.components:

WP components
WP components

.

Gå nu tilbage til edit.js-filen og se nærmere på scriptet:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
	return (
		<p { ...useBlockProps() }>
			{ __(
				'Kinsta Academy Block – hello from the editor!',
				'ka-example-block'
			) }
		</p>
	);
}

Denne kode genererer en statisk blok med simpel, ikke-redigerbar tekst. Men vi kan nemt ændre tingene:

Startblokken i kodeeditoren.
Startblokken i kodeeditoren.

For at gøre teksten redigerbar skal du erstatte det nuværende <p> tag med en komponent, der gør inputindholdet redigerbart. Til det formål tilbyder Gutenberg den indbyggede RichText-komponent.

Tilføjelse af en indbygget komponent til din blok er en proces i 5 trin:

  1. Importer de nødvendige komponenter fra en WordPress-pakke
  2. Inddrag de tilsvarende elementer i din JSX-kode
  3. Definer de nødvendige attributter i filen block.json
  4. Definer handlers for hændelser
  5. Gem data

Trin 1: Importer de nødvendige komponenter fra en WordPress-pakke

Åbn nu filen edit.js og ændr følgende import -angivelse:

import { useBlockProps } from '@wordpress/block-editor';

…til:

import { useBlockProps, RichText } from '@wordpress/block-editor';

På denne måde importerer du funktionen useBlockProps og komponenten RichText fra pakken @wordpress/block-editor.

useBlockProps

Den useBlockProps React hook markerer blokkens wrapper-element:

Når du bruger API version 2, skal du bruge den nye useBlockProps hook i blokkens edit -funktion til at markere blokkens wrapper-element. Hook’en indsætter de attributter og hændelseshåndterer, der er nødvendige for at aktivere blokadfærd. Eventuelle attributter, som du ønsker at sende til blokelementet, skal sendes gennem useBlockProps, og den returnerede værdi skal spredes til elementet.

For at sige det enkelt: useBlockProps tildeler automatisk attributter og klasser til wrapper-elementet ( p -elementet i vores eksempel):

Elementer og klasser genereret af useBlockProps.
Elementer og klasser genereret af useBlockProps.

Hvis du fjerner useBlockProps fra wrapper-elementet, har du en simpel tekststreng uden adgang til blokfunktionalitet og stil:

Den samme blok uden useBlockProps.
Den samme blok uden useBlockProps.

Som vi forklarer senere, kan du også sende et objekt med egenskaber til useBlockProps for at tilpasse output.

RichText

RichText-komponenten giver et input, der kan redigeres med indhold, så brugerne kan redigere og formatere indholdet.

Du finder komponenten dokumenteret på GitHub på gutenberg/packages/block-editor/src/components/rich-text/README.md.

Trin 2: Medtag de tilsvarende elementer i din JSX-kode

...

const blockProps = useBlockProps();

return (
	<RichText 
		{ ...blockProps }
		tagName="p"
		onChange={ onChangeContent }
		allowedFormats={ [ 'core/bold', 'core/italic' ] }
		value={ attributes.content }
		placeholder={ __( 'Write your text...' ) }
	/>
);

Lad os kommentere koden linje for linje:

  • tagName — tag-navnet på det redigerbare HTML-element
  • onChange — funktion, der kaldes, når elementets indhold ændres
  • allowedFormats — et array af tilladte formater. Som standard er alle formater tilladt
  • value — den HTML-streng, der skal gøres redigerbar
  • placeholder — placeholder-tekst, der skal vises, når elementet er tomt

Trin 3: Definer de nødvendige attributter i block.json-filen: Trin 3: Definer de nødvendige attributter i block.json-filen

Attributter giver oplysninger om de data, der er gemt af en blok, såsom indhold, baggrundsfarve, URL’er osv.

Du kan indstille et vilkårligt antal attributter i et attributes -objekt i key/value-par, hvor nøglen er attributnavnet og værdien attributdefinitionen.

Åbn nu filen block.json, og tilføj følgende attributes prop:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	}
},

Attributten content gør det muligt at gemme den tekst, som brugeren har indtastet i det redigerbare felt:

  • type angiver den type data, der er gemt af attributten. Typen er påkrævet, medmindre du definerer en enum -egenskab.
  • source definerer, hvordan attributværdien udtrækkes fra indlægsindholdet. I vores eksempel er det HTML-indholdet. Bemærk, at hvis du ikke angiver en kildeegenskab, gemmes data i blokafgrænseren (læs mere).
  • selector er et HTML-tag eller en anden selector, f.eks. et klassens navn eller en id-attribut.

Vi giver funktionen Edit et objekt med egenskaber. Så gå tilbage til edit.js-filen og lav følgende ændring:

export default function Edit( { attributes, setAttributes } ) { ... }

Trin 4: Definer event handlers

RichText -elementet har en onChange -attribut, som giver en funktion, der skal kaldes, når elementets indhold ændres.

Lad os definere denne funktion og se hele edit.js-scriptet:

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...' ) }
		/>
	);
}

Gem nu filen, og gå tilbage til dit WordPress-dashboard, opret et nyt indlæg eller en ny side og tilføj din brugerdefinerede blok:

Output af RichText-komponenten i Block Editor.
Output af RichText-komponenten i Block Editor.

Tilføj noget tekst, og skift til kodevisning. Her er, hvordan din kode skal se ud:

<!-- wp:ka-example-block/ka-example-block -->
<p class="wp-block-ka-example-block-ka-example-block">Kinsta Academy Block – hello from the saved content!</p>
<!-- /wp:ka-example-block/ka-example-block -->

Som du kan se, har indholdet af din blok ændret sig, hvis du skifter til kode-editoren. Det skyldes, at du skal ændre filen save.js for at gemme brugerinput i databasen, når indlægget gemmes.

Trin 5: Gem data

Åbn nu filen save.js og ændr scriptet som følger:

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 } 
		/>
	);
}

Det er det, vi gør her:

  • Importer komponenten RichText fra pakken block-editor.
  • Overfør flere egenskaber via et objektargument til save -funktionen (i dette eksempel overfører vi kun attributes -egenskaben)
  • Returner indholdet af komponenten RichText
Blokindholdet er blevet gemt i databasen
Blokindholdet er blevet gemt i databasen

Du kan læse mere om komponenten RichText i Block Editor Handbook og finde den fulde liste over rekvisitter på Github.

Lad os nu tage det et skridt videre. I det næste afsnit lærer du, hvordan du tilføjer kontrolelementer til blokværktøjslinjen.

Tilføjelse af kontrolelementer til blokværktøjslinjen

Blokværktøjslinjen indeholder et sæt kontroller, der giver brugerne mulighed for at manipulere dele af blokindholdet. For hver kontrol i værktøjslinjen finder du en komponent:

Den centrale blokværktøjslinje for afsnit.
Den centrale blokværktøjslinje for afsnit.

Du kan f.eks. tilføje en kontrol for tekstjustering til din blok. Det eneste, du skal gøre, er at importere to komponenter fra pakken @wordpress/block-editor.

Vi gennemgår de samme trin som i det foregående eksempel:

  1. Import af nødvendige komponenter fra WordPress-pakker
  2. Medtag de tilsvarende elementer i din JSX-kode
  3. Definer de nødvendige attributter i block.json-filen
  4. Definer event handlers
  5. Gem data

Trin 1: Importer BlockControls og AlignmentControl-komponenter fra @wordpress/block-editor

For at tilføje en AlignmentControl til blokværktøjslinjen har du brug for to komponenter:

  • BlockControls gør en dynamisk værktøjslinje med kontrolelementer (udokumenteret).
  • AlignmentControl renderer en dropdown-menu, der viser justeringsmuligheder for den valgte blok (læs mere)

Åbn filen edit.js og rediger import -erklæringen som vist nedenfor:

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls 
} from '@wordpress/block-editor';

Trin 2: Tilføj BlockControls og AlignmentControl-elementer

Gå til funktionen Edit og indsæt <BlockControls /> -elementet på samme niveau som <RichText />. Tilføj derefter og <AlignmentControl /> inden for <BlockControls />:

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 } }
			/>
		</>
	);
}

I koden ovenfor er <> og </> den korte syntaks til at deklarere React-fragmenter, som er den måde, hvorpå vi returnerer flere elementer i React.

I dette eksempel har AlignmentControl to attributter:

  • value giver den aktuelle værdi for elementet
  • onChange giver en hændelseshåndtering, der skal køres, når værdien ændres

Vi har også defineret yderligere attributter for RichText -elementet (se den fulde liste over attributter med eksempler)

Trin 3: Definer align-attributten i block.json

Gå nu til filen block.json, og tilføj attributten align:

"align": {
	"type": "string",
	"default": "none"
}

Når du er færdig, skal du gå tilbage til blok-editoren, opdatere siden og vælge blokken. Du bør se en fejlmeddelelse i din blok.

Blokken viser en fejlmeddelelse

Årsagen er, at vi ikke har defineret vores event handler endnu.

Trin 4: Definer eventhandlerne

Nu definerer vi onChangeAlign:

const onChangeAlign = ( newAlign ) => {
	setAttributes( { 
		align: newAlign === undefined ? 'none' : newAlign, 
	} )
}

Hvis newAlign er undefined, så sætter vi newAlign til none. Ellers bruger vi newAlign.

Vores edit.js-script burde være færdigt (for nu):

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 } }
			/>
		</>
	);
}

Nu kan du gå tilbage til editoren og justere blokindholdet. Din blok bør nu vise en justeringsværktøjslinje på flotteste vis.

Vores blok har nu en værktøjslinje til justering
Vores blok har nu en værktøjslinje til justering

Men hvis du gemmer indlægget, vil du se, at indholdet af din blok ikke er justeret på forsiden, som det er i blokredigeringsprogrammet. Det skyldes, at vi skal ændre funktionen save for at gemme blokindhold og attributter i databasen.

Trin 5: Gem data

Åbn save.js og ændr save -funktionen som følger:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ attributes.content } 
			style={ { textAlign: attributes.align } }
		/>
	);
}

Endelig kan du for at gøre koden mere læsbar udtrække de enkelte egenskaber fra attribute -objektet ved hjælp af destrukturerings tildelingssyntaksen for at gøre koden mere læsbar:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align } }
		/>
	);
}

Du kan gøre det samme i edit.js-filen.

Gem nu filen, og skift til Code Editor. Blokkoden skal se nogenlunde sådan her ud:

<!-- wp:ka-example-block/ka-example-block {"align":"right"} -->
<p class="wp-block-ka-example-block-ka-example-block" style="text-align:right">This is my first editable <strong>Gutenberg</strong> <em>block</em> 😎</p>
<!-- /wp:ka-example-block/ka-example-block -->
Kontrol af kontrolelementer på værktøjslinjen for blokke
Kontrol af kontrolelementer på værktøjslinjen for blokke

Og det er det! Du har netop tilføjet en justeringskontrol til din bloks værktøjslinje 🤓

Du kan læse mere om kontrolelementer i blokværktøjslinjen i Håndbog for blokredigering.

Tilpasning af blokindstillingssidebar

Du kan også tilføje kontrolelementer til blokindstillingssidebar (eller endda oprette en ny sidebar til dit program).

API’en indeholder en InspectorControls -komponent til dette.

I håndbogen Block Editor Handbook forklares det, hvordan du bruger Settings Sidebar:

Settings Sidebar bruges til at vise indstillinger, der bruges mindre ofte, eller indstillinger, der kræver mere plads på skærmen. Settings Sidebar bør kun bruges til indstillinger på blokniveau.

Hvis du har indstillinger, der kun påvirker udvalgt indhold i en blok (f.eks. “fed” indstilling for udvalgt tekst i et afsnit) , skal du ikke placere den i Indstillinger Sidebar. Sidebaren Indstillinger vises også, når du redigerer en blok i HTML-tilstand, så den bør kun indeholde indstillinger på blokniveau.

Igen:

  1. Import af nødvendige komponenter fra WordPress-pakker
  2. Medtag de tilsvarende elementer i din JSX-kode
  3. Definer de nødvendige attributter i block.json-filen
  4. Definer hændelseshåndterer
  5. Gem data

Trin 1. Importer InspectorControls og PanelColorSettings-komponenter fra @wordpress/block-editor

Du kan tilføje flere kontroller for at give brugerne mulighed for at tilpasse specifikke aspekter af blokken. Du kan f.eks. give et farvekontrolpanel. For at gøre det skal du importere komponenterne InspectorControls og PanelColorSettings fra modulet block-editor:

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls,
	InspectorControls,
	PanelColorSettings
} from '@wordpress/block-editor';

Trin 2: Medtag de tilsvarende elementer i din JSX-kode

Nu kan du tilføje de tilsvarende elementer til den JSX, der returneres af Edit -funktionen:

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();

	const { content, align, backgroundColor, textColor } = attributes;

	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<InspectorControls>
				<PanelColorSettings 
					title={ __( 'Color settings', 'ka-example-block' ) }
					initialOpen={ false }
					colorSettings={ [
						{
						  value: textColor,
						  onChange: onChangeTextColor,
						  label: __( 'Text color', 'ka-example-block' )
						},
						{
						  value: backgroundColor,
						  onChange: onChangeBackgroundColor,
						  label: __( 'Background color', 'ka-example-block' )
						}
					] }
				/>
			</InspectorControls>
			<BlockControls>
				<AlignmentControl
					value={ align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
			/>
		</>
	);
}

Bemærk, at vi også har opdateret style -attributten for RichText -elementet:

<RichText 
	 { ...blockProps }
	 tagName="p"
	 onChange={ onChangeContent }
	 allowedFormats={ [ 'core/bold', 'core/italic' ] }
	 value={ content }
	 placeholder={ __( 'Write your text...' ) }
	 style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>

Trin 3: Definer de nødvendige attributter i block.json

Nu defineres attributterne backgroundColor og textColor i filen block.json:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"backgroundColor": {
		"type": "string"
	},	 
	"textColor": {
		"type": "string"
	}
},

Trin 4: Definer hændelseshåndteringsenhederne

Nu skal du definere to funktioner til at opdatere backgroundColor og textColor ved brugerinput:

const onChangeBackgroundColor = ( newBackgroundColor ) => {
	setAttributes( { backgroundColor: newBackgroundColor } )
}

const onChangeTextColor = ( newTextColor ) => {
	setAttributes( { textColor: newTextColor } )
}

Trin 5: Gem data

Et sidste skridt: Åbn filen save.js og ændr scriptet som følger

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 } }
		/>
	);
}

Gem filen, og tjek blokken i editoren. Du vil måske finde en uvelkommen overraskelse: en fejlmeddelelse, der fortæller dig, at blokken indeholder uventet eller ugyldigt indhold.

Fejlmeddelelse om uventet eller ugyldigt indhold
Fejlmeddelelse om uventet eller ugyldigt indhold

Dette sker, fordi filen save.js er ændret, og den kode, der er gemt i databasen, ikke stemmer overens med den kode, der er brugt i editoren.

For at løse dette skal du opdatere siden, slette enhver forekomst af din blok og tilføje den igen til dit indlæg:

Panelet med farveindstillinger i blokken Indstillinger sidebar
Panelet med farveindstillinger i blokken Indstillinger sidebar

Foretag dine ændringer, gem indlægget, og se det i frontend. Nu bør de ændringer, du har foretaget i blokeditoren, afspejles på forsiden af webstedet.

Den brugerdefinerede blok fungerer nu korrekt på forsiden
Den brugerdefinerede blok fungerer nu korrekt på forsiden

I dette afsnit skal du tilføje nye komponenter til din bloktype:

  • En ExternalLink -komponent, der giver brugerne mulighed for at tilføje et tilpasseligt link til din brugerdefinerede blok
  • Flere sidebar-kontroller, der giver brugerne mulighed for at tilpasse linkindstillingerne

Trin 1. Importer komponenter fra @wordpress/components

Nu skal du importere flere komponenter fra @wordpress/components. Åbn din edit.js-fil, og tilføj følgende import -anvisning:

import {
	TextControl,
	PanelBody,
	PanelRow,
	ToggleControl,
	ExternalLink
} from '@wordpress/components';
  • PanelBody tilføjer en sammenklappelig container til Settings Sidebar.
  • PaneRow producerer en generisk container til sidebar-kontroller.
  • TextControl giver en tekstindtastningskontrol.
  • ToggleControl giver en toggle, der gør det muligt for brugerne at aktivere/deaktivere en bestemt indstilling
  • ExternalLink er en simpel komponent til at tilføje et eksternt link.

Trin 2. Indsæt de tilsvarende elementer i din JSX-kode

Du skal først tilføje ExternalLink -elementet på samme niveau som RichText i en div -container:

<div { ...blockProps }>
	<RichText 
		...
	/>
	<ExternalLink 
		href={ kaLink }
		className="ka-button"
		rel={ hasLinkNofollow ? "nofollow" : "" }
	>
			{ linkLabel }
	</ExternalLink>

</div>

ExternalLink -elementet er ikke dokumenteret, så vi henviser til selve elementet for at få en liste over tilgængelige attributter. Her bruger vi attributterne href, className og rel.

Som standard er værdien af attributten rel indstillet til noopener noreferrer. Vores kode tilføjer nøgleordetnofollow til rel -attributten i det resulterende a -tag, når vi slår omskiftereguleringen til.

Nu kan du tilføje linkindstillinger til bloksidebaren.

Først skal du tilføje et PanelBody -element inden for InspectorControls på samme niveau som PanelColorSettings:

<InspectorControls>
	<PanelColorSettings 
	...
	/>
	<PanelBody 
		title={ __( 'Link Settings' )}
		initialOpen={true}
	>
	...
	</PanelBody>
</InspectorControls>

Her er hvad vi gør med dette:

  1. Attributten title giver panelets titel.
  2. initialOpen indstiller, om panelet er åbent i starten eller ej.

Derefter tilføjer vi to PanelRow -elementer inden for PanelBody, og et TextControl -element inden for hvert PanelRow:

<PanelBody 
	title={ __( 'Link Settings', 'ka-example-block' )}
	initialOpen={true}
>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'KA link', 'ka-example-block' )}
				value={ kaLink }
				onChange={ onChangeKaLink }
				help={ __( 'Add your Academy link', 'ka-example-block' )}
			/>
		</fieldset>
	</PanelRow>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'Link label', 'ka-example-block' )}
				value={ linkLabel }
				onChange={ onChangeLinkLabel }
				help={ __( 'Add link label', 'ka-example-block' )}
			/>
		</fieldset>
	</PanelRow>
</PanelBody>

Ovenstående kode skulle nu se ret ligetil ud. De to tekstkontroller giver brugerne mulighed for at indstille link label og URL.

Vi tilføjer også en yderligere PanelRow med en ToggleControl for at slå en bestemt indstilling til/fra, f.eks. om en attribut skal medtages eller ej:

<PanelRow>
	<fieldset>
		<ToggleControl
			label="Add rel = nofollow"
			help={
				hasLinkNofollow
					? 'Has rel nofollow.'
					: 'No rel nofollow.'
			}
			checked={ hasLinkNofollow }
			onChange={ toggleNofollow }
		/>
	</fieldset>
</PanelRow>

Trin 3: Definer de nødvendige attributter i block.json

Nu defineres attributterne kaLink, linkLabel og hasLinkNofollow i filen block.json:

"kaLink": {
	"type": "string",
	"default": ""
},
"linkLabel": {
	"type": "string",
	"default": "Check it out!"
},
"hasLinkNofollow": {
	"type": "boolean",
	"default": false
}

Der er ikke mere at tilføje her! Lad os gå videre til at definere hændelsesbehandlingsfunktionerne.

Trin 4: Definer hændelseshåndteringsfunktionerne

Gå tilbage til edit.js-filen, tilføj de nye attributter til attributes-objektet, og tilføj følgende funktioner:

const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

const onChangeKaLink = ( newKaLink ) => {
	setAttributes( { kaLink: newKaLink === undefined ? '' : newKaLink } )
}

const onChangeLinkLabel = ( newLinkLabel ) => {
	setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}

const toggleNofollow = () => {
	setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}

Disse funktioner opdaterer de tilsvarende attributværdier ved brugerinput.

Trin 5: Gem data

Til sidst skal vi opdatere funktionen save i save.js:

export default function save( { attributes } ) {
	
	const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save( {
		className: `has-text-align-${ align }`
	} );
	
	return (
		<div 
			{ ...blockProps }
			style={ { backgroundColor: backgroundColor } }
		>
			<RichText.Content 
				tagName="p" 
				value={ content } 
				style={ { color: textColor } }
			/>
			<p>
				<a 
					href={ kaLink }
					className="ka-button"
					rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
				>
					{ linkLabel }
				</a>
			</p>
		</div>
	);
}

Bemærk, at vi her har brugt et almindeligt a -element i stedet for ExternalLink.

Du kan se resultatet i billedet nedenfor.

Panelet med linkindstillinger i blokindstillingen Sidebar
Panelet med linkindstillinger i blokindstillingen Sidebar

Tilføjelse af flere blokstilarter

I et tidligere afsnit lærte du, hvordan du tilføjer en blokværktøjslinje, der giver brugerne mulighed for at justere brugerinput. Vi kan tilføje flere stilkontrolelementer til blokværktøjslinjen, men vi kan også give et sæt foruddefinerede blokstilarter, som brugeren kan vælge imellem med et enkelt klik.

Til dette formål vil vi bruge en nyttig funktion i Block API’et: Block Styles.

Det eneste, du skal gøre, er at definere egenskaben block.json styles og erklære de tilsvarende stilarter i dine stilark.

Du kan f.eks. tilføje følgende array af stilarter:

"styles": [
	{
		"name": "default",
		"label": "Default",
		"isDefault": true
	},
	{
		"name": "border",
		"label": "Border"
	}
],

Dermed har du blot tilføjet en standardstil og en ekstra stil kaldet border. Gå nu tilbage til blokeditoren:

To præfabrikerede blokformater.
To præfabrikerede blokformater.

Stilene vil være tilgængelige for brugeren ved at klikke på blokomskifteren og derefter kigge efter panelet Stilarter i blokindstillingerne Sidebar.

Vælg en stil, og tjek de klasser, der anvendes på p -elementet. Højreklik på blokken og Inspicér. Der er blevet tilføjet en ny klasse med et navn, der er struktureret som følger:

is-style-{style-name}

Hvis du har markeret stilen “Border”, tilføjes der en klasse is-style-border til elementet p. Hvis du har markeret stilen “Default”, tilføjes der i stedet en is-style-default -klasse.

Nu skal du kun angive CSS-egenskaberne. Åbn filen editor.scss og erstat de nuværende stilarter med følgende:

.wp-block-ka-example-block-ka-example-block {
    padding: 4px;
}

Nu kan du gøre det samme med style.scss. Som vi nævnte ovenfor, anvendes stilarter, der er defineret i style.scss, både i frontend og i editoren:

.wp-block-ka-example-block-ka-example-block {
	&.is-style-default{
		border: 0;
        background-color: #FFE2C7;
	}
	&.is-style-border{
		border: 2px solid #000;
        border-radius: 16px;
        background-color: #F6F6F6;
	}
}

Og det var det! Opdater siden, og hav det sjovt med dine nye blokformater:

Blokstile sammenlignet
Blokstile sammenlignet

Indlejring af Gutenberg-blokke med InnerBlocks-komponenten

Selv om vores brugerdefinerede blok er fuldt funktionel, er den stadig ikke særlig tiltalende. For at gøre den mere engagerende for publikum kunne vi tilføje et billede.

Dette kan tilføje et lag af kompleksitet til vores blok, men heldigvis er det ikke besværligt, fordi Gutenberg indeholder en specifik komponent, som du kan bruge til at skabe en struktur af indlejrede blokke.

Komponenten InnerBlocks er defineret som følger:

InnerBlocks eksporterer et par komponenter, som kan bruges i blokimplementeringer for at aktivere indlejret blokindhold.

Først skal du oprette en ny .js-fil i src-mappen. I vores eksempel kalder vi denne fil container.js.

Nu skal du importere den nye ressource i filen index.js:

import './container';

Gå tilbage til container.js og importer de nødvendige komponenter:

import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
	useBlockProps, 
	InnerBlocks 
} from "@wordpress/block-editor";

Det næste skridt er at definere en skabelon, der giver den struktur, som blokkene skal placeres i. I det følgende eksempel definerer vi en skabelon bestående af to kolonner, der indeholder en kerneblok Image-blok og vores brugerdefinerede blok:

const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
	[ 'core/column', { templateLock: 'all' }, [
		[ 'core/image' ],
	] ],
	[ 'core/column', { templateLock: 'all' }, [
		[ 'ka-example-block/ka-example-block', { placeholder: 'Enter side content...' } ],
	] ],
] ] ];

Skabelonen er struktureret som et array af blockTypes (bloknavn og valgfrie attributter).

I koden ovenfor brugte vi flere attributter til at konfigurere kolonne- og kolonneblokkene. Navnlig låser attributten templateLock: 'all' kolonneblokkene, så brugeren ikke kan tilføje, omarrangere eller slette eksisterende blokke. templateLock kan antage en af følgende værdier:

  • all — InnerBlocks er låst, og der kan ikke tilføjes, omarrangeres eller fjernes blokke.
  • insert — Blokke kan kun omarrangeres eller fjernes.
  • false — Skabelonen er ikke låst.

Skabelonen tildeles derefter til InnerBlocks -elementet:

<InnerBlocks
	template={ TEMPLATE }
	templateLock="all"
/>

For at undgå kompatibilitetsproblemer har vi også tilføjet en templateLock -attribut til InnerBlocks -elementet (se også problem #17262 og pull #26128).

Her er vores endelige container.js-fil:

registerBlockType('ka-example-block/ka-example-container-block', {
	title: __( 'KA Container block', 'ka-example-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>
		)
	},
});
Den endelige blok i blokeditoren
Den endelige blok i blokeditoren

Yderligere forbedringer

Vores blok er fuldt funktionel, men vi kunne forbedre den en smule med nogle små ændringer.

Vi tildelte attributten backgroundColor til det afsnit, der blev genereret af RichText -komponenten. Vi kan dog foretrække at tildele baggrundsfarven til containeren div:

Så ændre edit.js-filen og save.js divs som følger:

<div 
	{ ...blockProps }
	style={ { backgroundColor: backgroundColor } }
>
...
</div>

Dette vil give brugeren mulighed for at ændre baggrunden for hele blokken.

En mere relevant ændring vedrører derimod metoden useBlockProps. I den oprindelige kode definerede vi konstanten blockProps som følger

const blockProps = useBlockProps();

Men vi kan bruge useBlockProps mere effektivt ved at videregive et sæt egenskaber. Vi kan f.eks. importere classnames fra modulet classnames og indstille wrapperklassens navn i overensstemmelse hermed.

I det følgende eksempel tildeler vi et klassens navn baseret på værdien af attributten align (edit.js).s

import classnames from 'classnames';

...

export default function Edit( { attributes, setAttributes } ) {
	...
	
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}

	const blockProps = useBlockProps( {
		className: `has-text-align-${ align }`
	} );
	...
}

Vi foretager den samme ændring i filen save.js:

import classnames from 'classnames';

...

export default function save( { attributes } ) {
	...
	const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save( {
		className: `has-text-align-${ align }`
	} );
	...
}

Og det var det! Du kan nu køre buildet til produktion:

npm run build

Opsummering

Og her er vi så ved slutningen af denne utrolige rejse! Vi startede med konfigurationen af udviklingsmiljøet og endte med at skabe en komplet bloktype.

Som vi nævnte i indledningen, er et solidt kendskab til Node.js, Webpack, Babel og React afgørende for at skabe avancerede Gutenberg-blokke og positionere dig selv på markedet som en professionel Gutenberg-udvikler.

Men du behøver dog ikke at have etableret React-erfaring for at begynde at have det sjovt med blokudvikling. Blokudvikling kan give dig motivation og mål til at opnå stadig bredere færdigheder inden for teknologierne bag Gutenberg-blokke.

Denne guide er derfor langt fra komplet. Den er blot en introduktion til en lang række emner, der kan hjælpe dig med at komme i gang med at bygge dine allerførste Gutenberg-blokke.

Derfor anbefaler vi, at du uddyber din viden ved at læse omhyggeligt online dokumentation og vejledninger. Blandt de mange ressourcer, der er tilgængelige derude, anbefaler vi følgende:

Hvis du lige er begyndt med WordPress-udvikling, vil du måske gerne forstå de grundlæggende koncepter for frontend-udvikling. Her er en hurtig liste over ressourcer, der kan hjælpe dig med at komme i gang:

Og husk, at den komplette kode for eksemplerne i denne vejledning er tilgængelig på Gist.

Nu er det din tur: Har du udviklet nogle Gutenberg-blokke? Hvad er de største vanskeligheder, du har oplevet indtil videre? Lad os høre om dine erfaringer i kommentarerne!

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.