Jak dotąd w tej serii samouczków napisaliśmy cały kod wewnątrz registerBlockType()
funkcji edit
. Jest to w pełni możliwe i często zalecane, aby zamiast tego przypisać edycję do oddzielnego komponentu. W ten sposób możemy wykorzystać funkcje, takie jak stan komponentów i metody cyklu życia. Jest również znacznie czystszy, czytelny i zapewnia kod wielokrotnego użytku!
Jeśli nie jesteś zaznajomiony z tworzeniem komponentów React lub czym są metody stanu i cyklu życia, polecam najpierw zapoznać się z oficjalnym przewodnikiem Reacta na ten temat.
Definiowanie komponentu klasy dlaedit
Komponent można zdefiniować jako funkcję lub klasę. Dzięki komponentowi klasy możesz korzystać z funkcjonalności, takich jak na przykład metody stanu i cyklu życia. Jednak w nowszych wersjach Reacta (16+) możesz użyć hooków Reacta do symulacji stanu i metod cyklu życia wewnątrz komponentów funkcyjnych. Ale w tym samouczku skupimy się na tworzeniu komponentu klasy. To, co do tej pory stworzyliśmy w tej serii, „inline" w registerBlockType()
for edit
i save
, to komponenty funkcyjne.
Aby zdefiniować komponent klasy, rozszerzamy WordPress’ Component
(w wp.element
pakiecie), dokładnie tak, jak rozszerzasz komponent klasy do React.Component
.
Pamiętaj, że komponent klasy musi zawierać funkcję render()
. A ze względu na to, jak działa JavaScript, Twoja klasa musi być zdefiniowana przed registerBlockType()
wywołaniem (najpierw zapisz swój komponent klasy w pliku i zachowaj registerBlockType()
go. Później w tym poście nauczymy się rozdzielać komponenty w osobnych plikach, eksportować i dołączać ich).
W skrócie tak:
Rekwizyty z edit
są automatycznie stosowane do naszego komponentu. Nie zapominaj, że komponent klasy musisz odwołać się do props za pomocą this.props
. W rdzeniu WordPress Gutenberg często używa się oddzielnych komponentów dla edit
funkcji, ponieważ najczęściej zawierają one znacznie więcej kodu. Funkcję save
można często pozostawić registerBlockType()
, chyba że zawiera również dużo kodu.
Robiąc to, możesz teraz napisać swój komponent, tak jak w przypadku Reacta. Możesz dodawać funkcje, konstruktora, metody stanu i cyklu życia.
Oto kod, który znaleźliśmy w ostatnim kroku, przekonwertowany na komponent klasy:
Jeśli zdestrukturyzowałeś się attributes
z setAttributes
rekwizytów, tak jak my, wszystko, co musisz zmienić, przechodząc do osobnego komponentu klasy, to zmiana jednej linii; #9
od props
do this.props
. Cały kod będzie działał tak jak poprzednio, bez naprawiania czegokolwiek innego. Na tym polega piękno destrukturyzacji. Gdybyś go nie zdestrukturyzował i nie odniósł się np props.attributes
. bezpośrednio, musiałbyś dodać this.
przed wszystkimi indywidualnymi odniesieniami do attributes
i setAttributes
wszędzie.
Zacznijmy robić rzeczy, które teraz możemy zrobić z komponentem klasy!
Definiowanie funkcji ithis
Oczywiście tak, możesz zdefiniować funkcje z edit
komponentu funkcji, przed wywołaniem return
. Ale osobiście zawsze wolałem rozdzielać funkcjonalność według logiki. Uważam, że lepiej jest oddzielić funkcje dla logiki i innych celów poza funkcją odpowiedzialną za renderowanie danych wyjściowych. Niektórzy ludzie wolą również wywoływać funkcje w zdarzeniach, zamiast robić je w linii, tak jak robiliśmy to do tej pory (na przykład robiąc setAttributes()
) onChange
.
W tej chwili nasz kod ma dwie rzeczy, które mogą być korzystne, aby przejść do funkcji; InspectorControls
i BlockControls
. To znacznie skróci return
nasz kod i sprawi, że nasz kod będzie łatwiejszy do odczytania.
Definiujemy dwie funkcje, które zwracają cały InspectorControls
blok i cały BlockControls
blok. Używając funkcji strzałek (functionName =() => { ... }
) mamy pełny dostęp do this
chwytania rekwizytów. Jeśli nie wykonałeś ostatniej części kroku 1 – konfiguracji Babel z najnowszą składnią, otrzymasz błędy kompilacji. Musiałbyś uciec się do stworzenia konstruktora i powiązania this
dla każdej funkcji. Możesz przeczytać więcej o obsłudze this
na początku strony FAQ Reacta.
Pamiętaj też, że ponieważ jesteśmy teraz w klasie, musisz wywołać wszystkie jej funkcje za pomocą z this.
przodu.
Zwróć uwagę, że pominąłem rzeczywistą zawartość InspectorControls
i BlockControls
aby kod był krótszy. Nic w ich kodzie nie musi się zmieniać.
Korzystamy również z faktu, że return
instrukcja może również zwrócić tablicę. Wszystko w tablicy będzie renderowane jak zwykle w kolejności, w jakiej się znajduje. Ułatwia nam to wywoływanie funkcji bezpośrednio w return
instrukcji.
Oczywiście można również zdefiniować metody cyklu życia, takie jak componentDidMount()
. Nie ma różnicy w robieniu tego w komponentach Gutenberga niż w React.
Konstruktor i używanie stanu
Spróbujmy zaimplementować stan w naszym komponencie. Należy pamiętać, że stan jest tylko czymś przechowywanym tymczasowo w naszym komponencie klasy i nie jest nigdzie zapisywany – na przykład w atrybutach. Chodzi tylko o to, by mieć kontrolę nad – no cóż – stanem Twojego komponentu. Typowe zastosowania stanu to używanie stanu jako flagi stanu podczas oczekiwania na powrót wywołania asynchronicznego, przechowywanie wyniku czegoś tymczasowego przed zapisaniem go w atrybucie lub implementowanie blokowych „trybów podglądu/edycji”.
Odwołujesz się do stanu i stanu aktualizacji, tak jak w React; z this.state
i setState()
. Normalnie zainicjowałbyś stan w konstruktorze. A jeśli chodzi o definiowanie konstruktora – jest dokładnie tak, jak w React – nie zapomnij przejść props
i to super(props)
też zrobić. W skrócie:
class FirstBlockEdit extends Component {
constructor(props) {
super(props);
this.state = {
example: 1
}
}
render() {
this.setState({ example: 2 });
console.log(this.state.example);
...
Przełącznik edycji/podglądu w trybie blokowania
Wykorzystajmy to, czego nauczyliśmy się w poprzednim kroku w paskach narzędzi, aby stworzyć „przełącznik trybów” dla naszego bloku. Wdrażamy pasek narzędzi z przyciskiem, który przełącza stan między trybem podglądu a trybem edycji. W trybie edycji blok otrzymuje jak zwykle dwa komponenty RichText. Ale po przejściu do trybu podglądu wyłączyliśmy edycję i renderowanie wyjścia bloku.
Najpierw tworzymy konstruktor i ustawiamy stan z jedną właściwością logiczną; editMode
który zaczyna się jako true
. Jest super(props)
niezbędny podczas definiowania konstruktora w komponencie React opartym na klasach.
class FirstBlockEdit extends Component {
constructor(props) {
super(props);
this.state = {
editMode: true
}
}
...
W naszej funkcji do wyprowadzania pasków narzędzi zmieniamy niestandardowy przycisk, który utworzyliśmy wcześniej (który tylko console.log
coś po kliknięciu). Na jego onClick
podpórce wywołujemy setState()
i negujemy bieżącą editMode
wartość logiczną. Aby ułatwić użytkownikowi zrozumienie, przełączamy się również między ikoną przycisku a etykietą. Np. gdy tryb podglądu jest aktywny, przycisk pokazuje etykietę „Edytuj” i ikonę ołówka, która jest powszechnie akceptowana jako edycja.
I wreszcie w głównej metodzie renderowania naszego bloku możemy zrobić, co chcemy. Ta część zależy od Ciebie – robisz to samo, co my zrobiliśmy z etykietą i ikoną na powyższym przycisku. Dodajemy dwa bloki danych wyjściowych, jeden if this.state.editMode
is true
(który powinien być zwykłymi edytowalnymi RichText
komponentami), a drugi if is false
.
Jako przykład używam dwóch komponentów WordPress z wp.components
; Placeholder
oraz Disabled
dla trybu podglądu. Komponent Placeholder
umieszcza twój blok w ładnym szarym polu, co czyni go naprawdę jasnym, że nie można go edytować. Pamiętaj, że jest dołączony do stylizacji, więc jeśli chcesz uzyskać doskonały podgląd, może to nie być dla Ciebie. A także Disabled
owijam wszystko wewnątrz komponentu, dzięki czemu wszystko wewnątrz jest nieedytowalne, niemożliwe do kliknięcia i przeciągania. To jest nasza nowa render()
funkcja w naszym komponencie:
Używam również komponentu Fragment
( wp.element
pakietu), który jest taki sam jak React.Fragment
. Jeśli go nie znasz, zawijamy w nim dane wyjściowe, gdy nie chcemy dodawać dodatkowych zbędnych opakowań HTML. W React wszystko musi mieć węzeł główny. Gdy tryb edycji jest aktywny (line #13
) wypisujemy dwa RichText
komponenty zaraz po sobie, więc potrzebujemy wokół nich rootnoda.
Gdy tryb podglądu jest aktywny (linia #29
) wyprowadzamy wartości dwóch RichText
składników. Podobnie jak w save
, używamy RichText.Content
do zwracania ich wartości zamiast małego edytora.
Komponent Placeholder
jest dostępny w stylu flex i domyślnie z wierszem flex-direction. Podanie true
we właściwościach isColumnLayout
zmienia ją na kolumnę flex-direction (więc wszystko się układa). Ale jak wspomniano wcześniej – możesz pominąć ten komponent i raczej wygenerować podgląd dokładnie tak, jak byłby w interfejsie.
I dzięki temu mamy przełącznik podglądu/edycji trybu blokowego. Oczywiście możesz dostosować zawartość „trybu edycji”, aby pokazać np. wejścia sterujące lub inne.
Możesz stworzyć tyle komponentów, ile chcesz, nie ograniczasz się tylko do posiadania jednego dla edit
funkcji! Po prostu utwórz więcej komponentów i uwzględnij je w return
zestawieniu. To jest właśnie idea Reacta – budowanie zamkniętych fragmentów kodu, z których każdy może obsługiwać swój własny stan i łączenie ich w złożone interfejsy użytkownika.