Crea un blocco Gutenberg personalizzato – Parte 7: crea i tuoi componenti personalizzati
Finora in questa serie di tutorial abbiamo scritto tutto il codice all’interno registerBlockType()
della edit
funzione di. È del tutto possibile, e spesso consigliato, assegnare invece la modifica a un componente separato. In questo modo possiamo utilizzare funzionalità come lo stato dei componenti e i metodi del ciclo di vita. È anche molto più pulito, leggibile e fornisce codice riutilizzabile!
Se non hai familiarità con la creazione di componenti React o quali sono i metodi di stato e ciclo di vita, ti consiglio di leggere prima la guida ufficiale di React su questo argomento.
Definizione di un componente di classe peredit
È possibile definire un componente come una funzione o una classe. Con un componente di classe puoi utilizzare funzionalità come ad esempio i metodi dello stato e del ciclo di vita. Tuttavia, nelle versioni più recenti di React (16+) è possibile utilizzare gli hook React per simulare lo stato e i metodi del ciclo di vita all’interno dei componenti della funzione. Ma in questo tutorial ci concentreremo sulla creazione di un componente di classe. Ciò che abbiamo creato finora in questa serie, "inline" in registerBlockType()
for edit
e save
, sono componenti di funzioni.
Per definire un componente di classe estendiamo WordPress’ Component
(nel wp.element
pacchetto), esattamente come estenderesti un componente di classe a React.Component
.
Tieni presente che il tuo componente di classe deve includere la funzione render()
. E a causa di come funziona Javascript, la tua classe deve essere definita prima della tua registerBlockType()
chiamata (scrivi prima il tuo componente di classe nel file e tienilo registerBlockType()
dopo di esso. Più avanti in questo post impareremo come separare i componenti in file separati, esportare e includere loro).
In breve, così:
Gli oggetti di scena da edit
vengono applicati automaticamente al nostro componente. Non dimenticare che un componente di classe è necessario fare riferimento agli oggetti di scena con this.props
. È comune nel core Gutenberg di WordPress utilizzare componenti separati per le edit
funzioni poiché molto spesso contengono molto più codice. La save
funzione può spesso essere lasciata a registerBlockType()
meno che non contenga anche molto codice.
In questo modo ora puoi scrivere il tuo componente proprio come faresti con React. È possibile aggiungere funzioni, costruttori, metodi dello stato e del ciclo di vita.
Questo è il codice che siamo finiti nell’ultimo passaggio, convertito in un componente di classe:
Se hai destrutturato attributes
e setAttributes
dagli oggetti di scena come abbiamo fatto noi, tutto ciò che devi cambiare quando ti muovi in un componente di classe separato è cambiare una riga; #9
da props
a this.props
. Tutto il codice funzionerà come prima senza correggere nient’altro. Questo è il bello della destrutturazione. Se non lo destrutturassi e ti riferissi ad esempio props.attributes
direttamente, avresti bisogno di aggiungere this.
davanti a tutti i riferimenti individuali a attributes
e setAttributes
ovunque.
Iniziamo a fare le cose che ora possiamo fare con un componente di classe!
Definizione di funzioni ethis
Certo, sì, puoi definire le funzioni dall’interno del edit
componente della funzione, prima di chiamare return
. Ma personalmente ho sempre preferito separare la funzionalità dalla logica. Trovo meglio separare le funzioni per la logica e altri scopi al di fuori della funzione responsabile del rendering dell’output. Alcune persone preferiscono anche chiamare funzioni negli eventi, invece di eseguirle in linea come abbiamo fatto finora (facendo setAttributes()
ad onChange
esempio).
A partire da ora il nostro codice ha due cose che potrebbero essere utili per passare alle funzioni; InspectorControls
e BlockControls
. Questo accorcerà return
notevolmente il nostro codice e renderà il nostro codice più facile da leggere.
Definiamo due funzioni che restituiscono l’intero InspectorControls
blocco e l’intero BlockControls
blocco. Usando le funzioni freccia (functionName =() => { ... }
) abbiamo pieno accesso this
per ottenere oggetti di scena. Se non hai eseguito l’ultima parte del passaggio 1, l’impostazione di Babel con le sintassi più recenti, otterrai errori di compilazione. Dovresti ricorrere alla creazione di un costruttore e all’associazione this
per ogni funzione. Puoi leggere di più sulla gestione this
all’inizio della pagina delle FAQ di React.
Ricorda anche che, poiché ora siamo in una classe, devi chiamare tutte le sue funzioni con this.
davanti.
Nota che ho escluso il contenuto effettivo di InspectorControls
e BlockControls
per mantenere il codice più breve. Niente nel loro codice deve cambiare.
Stiamo anche utilizzando il fatto che l’ return
istruzione può anche restituire un array. Tutto nell’array verrà visualizzato come al solito nell’ordine in cui si trova. Questo rende facile per noi chiamare le funzioni direttamente all’interno return
dell’istruzione.
Ovviamente puoi anche definire metodi del ciclo di vita, come componentDidMount()
. Non c’è differenza nel fare questi nei componenti Gutenberg rispetto a React.
Costruttore e stato di utilizzo
Proviamo a implementare lo stato nel nostro componente. Tieni presente che lo stato è solo qualcosa memorizzato temporaneamente all’interno del nostro componente di classe e non viene salvato da nessuna parte, ad esempio negli attributi. È solo per mantenere il controllo – beh – dello stato del tuo componente. Gli usi comuni dello stato sono l’utilizzo dello stato come flag di stato durante l’attesa del ritorno di una chiamata asincrona, il mantenimento del punteggio di qualcosa di temporaneo prima di salvarlo in un attributo o l’implementazione di "modalità di anteprima/modifica" del blocco.
Ti riferisci allo stato e allo stato di aggiornamento proprio come in React; con this.state
e setState()
. Normalmente inizializzeresti lo stato nel costruttore. E per quanto riguarda la definizione di un costruttore – è esattamente come in React – non dimenticare di passare props
e fare super(props)
altrettanto. In breve:
class FirstBlockEdit extends Component {
constructor(props) {
super(props);
this.state = {
example: 1
}
}
render() {
this.setState({ example: 2 });
console.log(this.state.example);
...
Commutatore di modifica/anteprima in modalità blocco
Usiamo ciò che abbiamo imparato nel passaggio precedente in Barre degli strumenti per creare un "selettore di modalità" per il nostro blocco. Implementiamo una barra degli strumenti con un pulsante che alterna lo stato tra anteprima e modalità di modifica. In modalità di modifica il blocco ottiene i due componenti RichText come al solito. Ma quando si passa alla modalità di anteprima, abbiamo disabilitato la modifica e il rendering dell’output del blocco.
Per prima cosa creiamo un costruttore e impostiamo lo stato con una proprietà booleana; editMode
che inizia come true
. È super(props)
necessario quando si definisce un costruttore in un componente React basato sulla classe.
class FirstBlockEdit extends Component {
constructor(props) {
super(props);
this.state = {
editMode: true
}
}
...
Nella nostra funzione per l’output delle barre degli strumenti cambiamo il pulsante personalizzato che abbiamo creato in precedenza (che solo console.log
qualcosa quando si fa clic su di esso). Sul suo onClick
supporto chiamiamo setState()
e neghiamo il editMode
valore booleano corrente. Per rendere più facile la comprensione per l’utente, passiamo anche all’icona e all’etichetta del pulsante. Ad esempio, quando la modalità di anteprima è attiva, il pulsante mostra l’etichetta “Modifica" e un’icona a forma di matita che è comunemente accettabile come modifica.
E infine all’interno del metodo di rendering principale per il nostro blocco, possiamo fare quello che vogliamo. Questa parte dipende davvero da te: fai lo stesso che abbiamo fatto con l’etichetta e l’icona sul pulsante in alto. Aggiungiamo due blocchi di output, uno if this.state.editMode
is true
(che dovrebbero essere i soliti RichText
componenti modificabili) e un altro se è false
.
Ad esempio sto usando due componenti di WordPress da wp.components
; Placeholder
e Disabled
per la modalità di anteprima. Il Placeholder
componente mette il tuo blocco in una bella casella grigia che rende davvero chiaro che non è modificabile. Tieni presente che viene fornito in allegato con lo stile, quindi se desideri un’anteprima perfetta, questo potrebbe non essere adatto a te. E avvolgo anche tutto all’interno di un Disabled
componente che rende tutto ciò che contiene non modificabile, non selezionabile e non trascinabile. Questa è la nostra nuova render()
funzione nel nostro componente:
Sto anche usando un componente Fragment
( wp.element
pacchetto) che è lo stesso di React.Fragment
. Se non hai familiarità con esso, avvolgiamo l’output al suo interno quando non vogliamo aggiungere ulteriori wrapper HTML non necessari. In React tutto deve avere un nodo radice. Quando la modalità di modifica è attiva (line #13
) emettiamo due RichText
componenti uno dopo l’altro, quindi abbiamo bisogno di un rootnode attorno a loro.
Quando la modalità di anteprima è attiva (line #29
) emettiamo i valori dei due RichText
componenti. Come facciamo in save
, usiamo RichText.Content
per restituire i loro valori invece del piccolo editor.
Il componente Placeholder
è disponibile in stile flex e di default con la riga in direzione flex. Fornire true
l’elica isColumnLayout
lo cambia in colonna in direzione flessibile (quindi tutto si impila). Ma come accennato in precedenza, potresti voler saltare questo componente e piuttosto generare la tua anteprima esattamente come sarebbe nel frontend.
E con ciò abbiamo un interruttore di anteprima/modifica in modalità blocco. Ovviamente puoi regolare il contenuto della "modalità di modifica" per mostrare ad esempio ingressi di controllo o altro.
Puoi creare tutti i componenti che desideri, non sei limitato ad averne solo uno per la edit
funzione! Crea semplicemente più componenti e includili all’interno di una return
dichiarazione. Questa è l’idea di React, in realtà: costruire pezzi di codice incapsulati, possibilmente ciascuno gestendo il proprio stato e combinandoli per creare interfacce utente complesse.