Cree un bloque de Gutenberg personalizado – Parte 7: Cree sus propios componentes personalizados
Hasta ahora, en esta serie de tutoriales, hemos escrito todo el código dentro registerBlockType()
de la edit
función. Es totalmente posible y, a menudo, se recomienda asignar la edición a un componente separado. Al hacerlo, podemos utilizar funciones como el estado de los componentes y los métodos del ciclo de vida. ¡También es mucho más limpio, legible y proporciona un código reutilizable!
Si no está familiarizado con la creación de componentes de React o con los métodos de estado y ciclo de vida, le recomiendo leer primero la guía oficial de React sobre este tema.
Definición de un componente de clase paraedit
Puede definir un componente como una función o una clase. Con un componente de clase, puede usar funciones como, por ejemplo, métodos de estado y ciclo de vida. Sin embargo, en las versiones más nuevas de React (16+) puede usar ganchos de React para simular métodos de estado y ciclo de vida dentro de los componentes de la función. Pero en este tutorial nos enfocaremos en crear un componente de clase. Lo que hemos creado hasta ahora en esta serie, "en línea" en registerBlockType()
for edit
y save
, son componentes de funciones.
Para definir un componente de clase, extendemos WordPress’ Component
(en el wp.element
paquete), exactamente como extendería un componente de clase a React.Component
.
Tenga en cuenta que su componente de clase debe incluir la función render()
. Y debido a cómo funciona Javascript, su clase debe definirse antes de su registerBlockType()
llamada (escriba su componente de clase primero en el archivo y manténgalo registerBlockType()
después. Más adelante en esta publicación, aprenderemos cómo separar componentes en archivos separados, exportar e incluir a ellos).
En resumen, así:
Los accesorios de edit
se aplican automáticamente a nuestro componente. No olvide que un componente de clase que necesita para referirse a accesorios con this.props
. Es común en el núcleo de WordPress Gutenberg usar componentes separados para las edit
funciones, ya que la mayoría de las veces contienen mucho más código. La save
función a menudo se puede dejar a registerBlockType()
menos que también contenga una gran cantidad de código.
Al hacer esto, ahora puede escribir su componente como lo haría con React. Puede agregar funciones, constructor, estado y métodos de ciclo de vida.
Este es el código que terminamos en el último paso, convertido en un componente de clase:
Si desestructuraste attributes
y setAttributes
usaste accesorios como lo hicimos nosotros, todo lo que necesitas cambiar cuando pasas a un componente de clase separado es cambiar una línea; #9
de props
a this.props
. Todo el código funcionará como antes sin arreglar nada más. Esa es la belleza de la desestructuración. Si no lo desestructuraste y lo mencionaste, por ejemplo props.attributes
, directamente, tendrías que agregarlo this.
delante de todas las referencias individuales ay en attributes
todas setAttributes
partes.
¡Comencemos a hacer cosas que ahora podemos hacer con un componente de clase!
Definición de funciones ythis
De acuerdo, sí, puede definir funciones desde edit
el componente de función, antes de llamar a return
. Pero personalmente siempre he preferido separar la funcionalidad por lógica. Me parece mejor separar las funciones para la lógica y otros fines fuera de la función responsable de representar la salida. Algunas personas también prefieren llamar funciones en eventos, en lugar de hacerlo en línea como lo hemos hecho hasta ahora (doing, setAttributes()
por onChange
ejemplo).
A partir de ahora, nuestro código tiene dos cosas que podrían ser beneficiosas para pasar a las funciones; InspectorControls
y BlockControls
. Esto lo acortará return
considerablemente y hará que nuestro código sea más fácil de leer.
Definimos dos funciones que devuelven el InspectorControls
bloque completo y el BlockControls
bloque completo. Mediante el uso de funciones de flecha (functionName =() => { ... }
) tenemos acceso completo this
para obtener accesorios. Si no realizó la última parte del paso 1: configurar Babel con las sintaxis más recientes, obtendrá errores de compilación. Tendría que recurrir a la creación de un constructor y un enlace this
para cada función. Puede leer más sobre el manejo this
al comienzo de la página de preguntas frecuentes de React.
También recuerde que debido a que estamos en una clase, ahora debe llamar a todas sus funciones al this.
frente.
Tenga en cuenta que he excluido el contenido real de InspectorControls
y BlockControls
para mantener el código más corto. Nada en su código necesita cambiar.
También estamos utilizando el hecho de que la return
declaración también puede devolver una matriz. Todo en la matriz se representará como de costumbre en el orden en que se encuentran. Esto nos facilita llamar funciones directamente dentro de la return
instrucción.
Obviamente, también puede definir métodos de ciclo de vida, como componentDidMount()
. No hay diferencia en hacer esto en los componentes de Gutenberg que en React.
Constructor y estado de uso
Intentemos implementar el estado en nuestro componente. Tenga en cuenta que el estado es solo algo almacenado temporalmente dentro de nuestro componente de clase y no se guarda en ningún lugar, como en los atributos. Es solo para mantener el control de, bueno, el estado de su componente. Los usos comunes del estado son usar el estado como un indicador de estado mientras se espera que regrese una llamada asíncrona, mantener la puntuación de algo temporal antes de guardarlo en un atributo o implementar "modos de vista previa/edición" de bloques.
Te refieres al estado y al estado de actualización como en React; con this.state
y setState()
. Normalmente inicializarías el estado en el constructor. Y en cuanto a definir un constructor, es exactamente como en React, no olvide pasar props
y hacer super(props)
también. En breve:
class FirstBlockEdit extends Component {
constructor(props) {
super(props);
this.state = {
example: 1
}
}
render() {
this.setState({ example: 2 });
console.log(this.state.example);
...
Conmutador de edición/vista previa del modo de bloque
Usemos lo que aprendimos en el paso anterior en Barras de herramientas para crear un "cambio de modo" para nuestro bloque. Implementamos una barra de herramientas con un botón que alterna el estado entre el modo de vista previa y el modo de edición. En el modo de edición, el bloque obtiene los dos componentes RichText como de costumbre. Pero al cambiar al modo de vista previa, deshabilitamos la edición y renderizamos la salida del bloque.
Primero creamos un constructor y configuramos el estado con una propiedad booleana; editMode
que comienza como true
. El super(props)
es necesario cuando se define un constructor en un componente React basado en clases.
class FirstBlockEdit extends Component {
constructor(props) {
super(props);
this.state = {
editMode: true
}
}
...
En nuestra función para generar las barras de herramientas, cambiamos el botón personalizado que creamos anteriormente (que solo console.log
algo al hacer clic en él). En su onClick
prop llamamos setState()
y negamos el editMode
valor booleano actual. Para que sea más fácil de entender para el usuario, también alternamos entre el icono y la etiqueta del botón. Por ejemplo, cuando el modo de vista previa está activo, el botón muestra la etiqueta "Editar" y un icono de lápiz que normalmente se acepta como edición.
Y, finalmente, dentro del método de representación principal de nuestro bloque, podemos hacer lo que queramos. Esta parte realmente depende de usted: haga lo mismo que hicimos con la etiqueta y el ícono en el botón de arriba. Agregamos dos bloques de salida, uno si this.state.editMode
es true
(que deberían ser los RichText
componentes editables habituales) y otro si es false
.
Como ejemplo, estoy usando dos componentes de WordPress de wp.components
; Placeholder
y Disabled
para el modo de vista previa. El Placeholder
componente coloca su bloque en un bonito cuadro gris que deja muy claro que no es editable. Tenga en cuenta que viene adjunto con estilo, por lo que si desea una vista previa perfecta, es posible que esta no sea para usted. Y también envuelvo todo dentro de un Disabled
componente que hace que todo el interior no se pueda editar, hacer clic ni arrastrar. Esta es nuestra nueva render()
función en nuestro componente:
También estoy usando un componente Fragment
( wp.element
paquete) que es el mismo que React.Fragment
. Si no está familiarizado con él, envolvemos la salida dentro de él cuando no queremos agregar envoltorios HTML adicionales innecesarios. En React todo debe tener un nodo raíz. Cuando el modo de edición está activo (línea #13
), generamos dos RichText
componentes uno detrás del otro, por lo que necesitamos un nodo raíz alrededor de ellos.
Cuando el modo de vista previa está activo (línea #29
), mostramos los RichText
valores de los dos componentes. Como hacemos en save
, usamos RichText.Content
para devolver sus valores en lugar del pequeño editor.
El componente Placeholder
viene en estilo flexible y por defecto con fila de dirección flexible. Proporcionar true
en el accesorio isColumnLayout
lo cambia a una columna de dirección flexible (para que todo se apila). Pero como se mencionó anteriormente, es posible que desee omitir este componente y generar su vista previa exactamente como lo haría en la interfaz.
Y con eso tenemos un conmutador de vista previa/edición del modo de bloque. Obviamente, puede ajustar el contenido del "modo de edición" para mostrar, por ejemplo, entradas de control o lo que sea.
Puede crear tantos componentes como desee, ¡no está limitado a tener solo uno para la edit
función! Simplemente cree más componentes e inclúyalos dentro de una return
declaración. Esa es la idea de React, en realidad: construir piezas de código encapsuladas, posiblemente cada una manejando su propio estado y combinándolas para crear interfaces de usuario complejas.