{"id":233536,"date":"2023-02-17T10:11:00","date_gmt":"2023-02-17T07:11:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233536"},"modified":"2022-11-11T00:13:35","modified_gmt":"2022-11-10T21:13:35","slug":"cree-un-bloque-de-gutenberg-personalizado-parte-7-cree-sus-propios-componentes-personalizados","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/cree-un-bloque-de-gutenberg-personalizado-parte-7-cree-sus-propios-componentes-personalizados\/","title":{"rendered":"Cree un bloque de Gutenberg personalizado &#8211; Parte 7: Cree sus propios componentes personalizados"},"content":{"rendered":"\n<p>Hasta ahora, en esta serie de tutoriales, hemos escrito todo el c\u00f3digo dentro <code>registerBlockType()<\/code>de la <code>edit<\/code>funci\u00f3n. Es totalmente posible y, a menudo, se recomienda asignar la edici\u00f3n a un componente separado. Al hacerlo, podemos utilizar funciones como el estado de los componentes y los m\u00e9todos del ciclo de vida. \u00a1Tambi\u00e9n es mucho m\u00e1s limpio, legible y proporciona un c\u00f3digo reutilizable!<\/p>\n<p>Si no est\u00e1 familiarizado con la creaci\u00f3n de componentes de React o con los m\u00e9todos de estado y ciclo de vida, le recomiendo leer primero <a href=\"https:\/\/reactjs.org\/docs\/state-and-lifecycle.html\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">la gu\u00eda oficial de React sobre este tema<\/a>.<\/p>\n<h2>Definici\u00f3n de un componente de clase para<code>edit<\/code><\/h2>\n<p>Puede definir un componente como una funci\u00f3n o una clase. Con un componente de clase, puede usar funciones como, por ejemplo, m\u00e9todos de estado y ciclo de vida. Sin embargo, en las versiones m\u00e1s nuevas de React (16+) puede usar ganchos de React para simular m\u00e9todos de estado y ciclo de vida dentro de los componentes de la funci\u00f3n. Pero en este tutorial nos enfocaremos en crear un componente de clase. Lo que hemos creado hasta ahora en esta serie, &quot;en l\u00ednea&quot; en <code>registerBlockType()<\/code>for <code>edit<\/code>y <code>save<\/code>, son componentes de funciones.<\/p>\n<p>Para definir un componente de clase, extendemos WordPress&#8217; <code>Component<\/code>(en el <code>wp.element<\/code>paquete), exactamente como extender\u00eda un componente de clase a <code>React.Component<\/code>.<\/p>\n<p>Tenga en cuenta que su componente de clase debe incluir la funci\u00f3n <code>render()<\/code>. Y debido a c\u00f3mo funciona Javascript, su clase debe definirse antes de su <code>registerBlockType()<\/code>llamada (escriba su componente de clase primero en el archivo y mant\u00e9ngalo <code>registerBlockType()<\/code>despu\u00e9s. M\u00e1s adelante en esta publicaci\u00f3n, aprenderemos c\u00f3mo separar componentes en archivos separados, exportar e incluir a ellos).<\/p>\n<p>En resumen, as\u00ed:<\/p>\n<pre><code>const { registerBlockType } = wp.blocks;\nconst { Component } = wp.element;\n\u00a0\nclass FirstBlockEdit extends Component {\n    render() {\n        const { attributes, setAttributes } = this.props;\n        return ...\n    }\n}\n\u00a0\nregisterBlockType('awp\/firstblock', {\n    title: 'My first block',\n    edit: FirstBlockEdit,\n    save: (props) =&gt; { \n        return ...\n    }\n});<\/code><\/pre>\n<p>Los accesorios de <code>edit<\/code>se aplican autom\u00e1ticamente a nuestro componente. No olvide que un componente de clase que necesita para referirse a accesorios con <code>this.props<\/code>. Es com\u00fan en el n\u00facleo de WordPress Gutenberg usar componentes separados para las <code>edit<\/code>funciones, ya que la mayor\u00eda de las veces contienen mucho m\u00e1s c\u00f3digo. La <code>save<\/code>funci\u00f3n a menudo se puede dejar a <code>registerBlockType()<\/code>menos que tambi\u00e9n contenga una gran cantidad de c\u00f3digo.<\/p>\n<p>Al hacer esto, ahora puede escribir su componente como lo har\u00eda con React. Puede agregar funciones, constructor, estado y m\u00e9todos de ciclo de vida.<\/p>\n<p>Este es el c\u00f3digo que terminamos en el \u00faltimo paso, convertido en un componente de clase:<\/p>\n<pre><code>const { registerBlockType } = wp.blocks;\nconst { Component } = wp.element;\nconst { RichText, InspectorControls, BlockControls, AlignmentToolbar } = wp.blockEditor;\nconst { ToggleControl, PanelBody, PanelRow, CheckboxControl, SelectControl, ColorPicker, Toolbar, IconButton } = wp.components;\n\u00a0\nclass FirstBlockEdit extends Component {\n\u00a0\n    render() {\n        const { attributes, setAttributes } = this.props;\n        const alignmentClass = (attributes.textAlignment != null)? 'has-text-align-' + attributes.textAlignment: '';\n\u00a0\n        return (&lt;div className={alignmentClass}&gt;\n                &lt;InspectorControls&gt;\n                    &lt;PanelBody\n                        title=\"Most awesome settings ever\"\n                        initialOpen={true}\n                    &gt;\n                        &lt;PanelRow&gt;\n                            &lt;ToggleControl\n                                label=\"Toggle me\"\n                                checked={attributes.toggle}\n                                onChange={(newval) =&gt; setAttributes({ toggle: newval })}\n                            \/&gt;\n                        &lt;\/PanelRow&gt;\n                        &lt;PanelRow&gt;\n                            &lt;SelectControl\n                                label=\"What's your favorite animal?\"\n                                value={attributes.favoriteAnimal}\n                                options={[\n                                    {label: \"Dogs\", value: 'dogs'},\n                                    {label: \"Cats\", value: 'cats'},\n                                    {label: \"Something else\", value: 'weird_one'},\n                                ]}\n                                onChange={(newval) =&gt; setAttributes({ favoriteAnimal: newval })}\n                            \/&gt;\n                        &lt;\/PanelRow&gt;\n                        &lt;PanelRow&gt;\n                            &lt;ColorPicker\n                                color={attributes.favoriteColor}\n                                onChangeComplete={(newval) =&gt; setAttributes({ favoriteColor: newval.hex })}\n                                disableAlpha\n                            \/&gt;\n                        &lt;\/PanelRow&gt;\n                        &lt;PanelRow&gt;\n                            &lt;CheckboxControl\n                                label=\"Activate lasers?\"\n                                checked={attributes.activateLasers}\n                                onChange={(newval) =&gt; setAttributes({ activateLasers: newval })}\n                            \/&gt;\n                        &lt;\/PanelRow&gt;\n                    &lt;\/PanelBody&gt;\n                &lt;\/InspectorControls&gt;\n                &lt;BlockControls&gt;\n                    &lt;AlignmentToolbar\n                        value={attributes.textAlignment}\n                        onChange={(newalign) =&gt; setAttributes({ textAlignment: newalign })}\n                    \/&gt;\n                    &lt;Toolbar&gt;\n                        &lt;IconButton\n                            label=\"My very own custom button\"\n                            icon=\"edit\"\n                            className=\"my-custom-button\"\n                            onClick={() =&gt; console.log('pressed button')}\n                        \/&gt;\n                    &lt;\/Toolbar&gt;\n                &lt;\/BlockControls&gt;\n                &lt;RichText \n                    tagName=\"h2\"\n                    placeholder=\"Write your heading here\"\n                    value={attributes.myRichHeading}\n                    onChange={(newtext) =&gt; setAttributes({ myRichHeading: newtext })}\n                \/&gt;\n                &lt;RichText\n                    tagName=\"p\"\n                    placeholder=\"Write your paragraph here\"\n                    value={attributes.myRichText}\n                    onChange={(newtext) =&gt; setAttributes({ myRichText: newtext })}\n                \/&gt;\n            &lt;\/div&gt;\n        );\n    }\n}\n\u00a0\nregisterBlockType('awp\/firstblock', {\n    title: 'My first block',\n    category: 'common',\n    icon: 'smiley',\n    description: 'Learning in progress',\n    keywords: ['example', 'test'],\n    attributes: {\n        myRichHeading: {\n            type: 'string',\n        },\n        myRichText: {\n            type: 'string',\n            source: 'html',\n            selector: 'p'\n        },\n        textAlignment: {\n            type: 'string',\n        },\n        toggle: {\n            type: 'boolean',\n            default: true\n        },\n        favoriteAnimal: {\n            type: 'string',\n            default: 'dogs'\n        },\n        favoriteColor: {\n            type: 'string',\n            default: '#DDDDDD'\n        },\n        activateLasers: {\n            type: 'boolean',\n            default: false\n        },\n    },\n    supports: {\n        align: ['wide', 'full']\n    },\n    edit: FirstBlockEdit,\n    save: (props) =&gt; { \n        const { attributes } = props;\n\u00a0\n        const alignmentClass = (attributes.textAlignment != null)? 'has-text-align-' + attributes.textAlignment: '';\n\u00a0\n        return (&lt;div className={alignmentClass}&gt;\n                &lt;RichText.Content \n                    tagName=\"h2\"\n                    value={attributes.myRichHeading}\n                \/&gt;\n                &lt;RichText.Content \n                    tagName=\"p\"\n                    value={attributes.myRichText}\n                \/&gt;\n                {attributes.activateLasers &amp;&amp; \n                    &lt;div className=\"lasers\"&gt;Lasers activated&lt;\/div&gt;\n                }\n            &lt;\/div&gt;\n        );\n    }\n});<\/code><\/pre>\n<p>Si desestructuraste <code>attributes<\/code>y <code>setAttributes<\/code>usaste accesorios como lo hicimos nosotros, todo lo que necesitas cambiar cuando pasas a un componente de clase separado es cambiar una l\u00ednea; <code>#9<\/code>de <code>props<\/code>a <code>this.props<\/code>. Todo el c\u00f3digo funcionar\u00e1 como antes sin arreglar nada m\u00e1s. Esa es la belleza de la desestructuraci\u00f3n. Si no lo desestructuraste y lo mencionaste, por ejemplo <code>props.attributes<\/code>, directamente, tendr\u00edas que agregarlo <code>this.<\/code>delante de todas las referencias individuales ay en <code>attributes<\/code>todas <code>setAttributes<\/code>partes.<\/p>\n<p>\u00a1Comencemos a hacer cosas que ahora podemos hacer con un componente de clase!<\/p>\n<h2>Definici\u00f3n de funciones y<code>this<\/code><\/h2>\n<p>De acuerdo, s\u00ed, puede definir funciones desde <code>edit<\/code>el componente de funci\u00f3n, antes de llamar a <code>return<\/code>. Pero personalmente siempre he preferido separar la funcionalidad por l\u00f3gica. Me parece mejor separar las funciones para la l\u00f3gica y otros fines fuera de la funci\u00f3n responsable de representar la salida. Algunas personas tambi\u00e9n prefieren llamar funciones en eventos, en lugar de hacerlo en l\u00ednea como lo hemos hecho hasta ahora (doing, <code>setAttributes()<\/code>por <code>onChange<\/code>ejemplo).<\/p>\n<p>A partir de ahora, nuestro c\u00f3digo tiene dos cosas que podr\u00edan ser beneficiosas para pasar a las funciones; <code>InspectorControls<\/code>y <code>BlockControls<\/code>. Esto lo acortar\u00e1 <code>return<\/code>considerablemente y har\u00e1 que nuestro c\u00f3digo sea m\u00e1s f\u00e1cil de leer.<\/p>\n<p>Definimos dos funciones que devuelven el <code>InspectorControls<\/code>bloque completo y el <code>BlockControls<\/code>bloque completo. Mediante el uso de funciones de flecha (<code>functionName =() =&gt; { ... }<\/code>) tenemos acceso completo <code>this<\/code>para obtener accesorios. Si no realiz\u00f3 la \u00faltima parte del paso 1: configurar Babel con las sintaxis m\u00e1s recientes, obtendr\u00e1 errores de compilaci\u00f3n. Tendr\u00eda que recurrir a la creaci\u00f3n de un constructor y un enlace <code>this<\/code>para cada funci\u00f3n. Puede leer m\u00e1s sobre el manejo <code>this<\/code>al comienzo de <a href=\"https:\/\/reactjs.org\/docs\/faq-functions.html\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">la p\u00e1gina de preguntas frecuentes de React<\/a>.<\/p>\n<p>Tambi\u00e9n recuerde que debido a que estamos en una clase, ahora debe llamar a todas sus funciones al <code>this.<\/code>frente.<\/p>\n<pre><code>class FirstBlockEdit extends Component {\n\u00a0\n    getInspectorControls =() =&gt; {\n        const { attributes, setAttributes } = this.props;\n\u00a0\n        return (&lt;InspectorControls&gt;\n                ...\n            &lt;\/InspectorControls&gt;\n        );\n    }\n\u00a0\n    getBlockControls = () =&gt; {\n        const { attributes, setAttributes } = this.props;\n\u00a0\n        return (&lt;BlockControls&gt;\n                ...\n            &lt;\/BlockControls&gt;\n        );\n    }\n\u00a0\n    render() {\n        const { attributes, setAttributes } = this.props;\n        const alignmentClass = (attributes.textAlignment != null)? 'has-text-align-' + attributes.textAlignment: '';\n\u00a0\n        return ([\n            this.getInspectorControls(),\n            this.getBlockControls(),\n            &lt;div className={alignmentClass}&gt;\n                &lt;RichText \n                    tagName=\"h2\"\n                    placeholder=\"Write your heading here\"\n                    value={attributes.myRichHeading}\n                    onChange={(newtext) =&gt; setAttributes({ myRichHeading: newtext })}\n                \/&gt;\n                &lt;RichText\n                    tagName=\"p\"\n                    placeholder=\"Write your paragraph here\"\n                    value={attributes.myRichText}\n                    onChange={(newtext) =&gt; setAttributes({ myRichText: newtext })}\n                \/&gt;\n            &lt;\/div&gt;\n        ]);\n    }\n}<\/code><\/pre>\n<p>Tenga en cuenta que he excluido el contenido real de <code>InspectorControls<\/code>y <code>BlockControls<\/code>para mantener el c\u00f3digo m\u00e1s corto. Nada en su c\u00f3digo necesita cambiar.<\/p>\n<p>Tambi\u00e9n estamos utilizando el hecho de que la <code>return<\/code>declaraci\u00f3n tambi\u00e9n puede devolver una matriz. Todo en la matriz se representar\u00e1 como de costumbre en el orden en que se encuentran. Esto nos facilita llamar funciones directamente dentro de la <code>return<\/code>instrucci\u00f3n.<\/p>\n<p>Obviamente, tambi\u00e9n puede definir m\u00e9todos de ciclo de vida, como <code>componentDidMount()<\/code>. No hay diferencia en hacer esto en los componentes de Gutenberg que en React.<\/p>\n<h2>Constructor y estado de uso<\/h2>\n<p>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\u00fan 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\u00edncrona, mantener la puntuaci\u00f3n de algo temporal antes de guardarlo en un atributo o implementar &quot;modos de vista previa\/edici\u00f3n&quot; de bloques.<\/p>\n<p>Te refieres al estado y al estado de actualizaci\u00f3n como en React; con <code>this.state<\/code>y <code>setState()<\/code>. Normalmente inicializar\u00edas el estado en el constructor. Y en cuanto a definir un constructor, es exactamente como en React, no olvide pasar <code>props<\/code>y hacer <code>super(props)<\/code>tambi\u00e9n. En breve:<\/p>\n<pre><code>class FirstBlockEdit extends Component {\n    constructor(props) {\n        super(props);\n\u00a0\n        this.state = {\n            example: 1\n        }\n    }\n\u00a0\n    render() {\n        this.setState({ example: 2 });\n        console.log(this.state.example);\n        ...<\/code><\/pre>\n<h3>Conmutador de edici\u00f3n\/vista previa del modo de bloque<\/h3>\n<p>Usemos lo que aprendimos en el paso anterior en Barras de herramientas para crear un &quot;cambio de modo&quot; para nuestro bloque. Implementamos una barra de herramientas con un bot\u00f3n que alterna el estado entre el modo de vista previa y el modo de edici\u00f3n. En el modo de edici\u00f3n, el bloque obtiene los dos componentes RichText como de costumbre. Pero al cambiar al modo de vista previa, deshabilitamos la edici\u00f3n y renderizamos la salida del bloque.<\/p>\n<p>Primero creamos un constructor y configuramos el estado con una propiedad booleana; <code>editMode<\/code>que comienza como <code>true<\/code>. El <code>super(props)<\/code>es necesario cuando se define un constructor en un componente React basado en clases.<\/p>\n<pre><code>class FirstBlockEdit extends Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            editMode: true\n        }\n    }\n    ...<\/code><\/pre>\n<p>En nuestra funci\u00f3n para generar las barras de herramientas, cambiamos el bot\u00f3n personalizado que creamos anteriormente (que solo <code>console.log<\/code>algo al hacer clic en \u00e9l). En su <code>onClick<\/code>prop llamamos <code>setState()<\/code>y negamos el <code>editMode<\/code>valor booleano actual. Para que sea m\u00e1s f\u00e1cil de entender para el usuario, tambi\u00e9n alternamos entre el icono y la etiqueta del bot\u00f3n. Por ejemplo, cuando el modo de vista previa est\u00e1 activo, el bot\u00f3n muestra la etiqueta &quot;Editar&quot; y un icono de l\u00e1piz que normalmente se acepta como edici\u00f3n.<\/p>\n<pre><code>getBlockControls = () =&gt; {\n    const { attributes, setAttributes } = this.props;\n    return (&lt;BlockControls&gt;\n            &lt;AlignmentToolbar\n                value={attributes.textAlignment}\n                onChange={(newalign) =&gt; setAttributes({ textAlignment: newalign })}\n            \/&gt;\n            &lt;Toolbar&gt;\n                &lt;IconButton\n                    label={ this.state.editMode? \"Preview\": \"Edit\" }\n                    icon={ this.state.editMode? \"format-image\": \"edit\" }\n                    onClick={() =&gt; this.setState({ editMode: !this.state.editMode })}\n                \/&gt;\n            &lt;\/Toolbar&gt;\n        &lt;\/BlockControls&gt;\n    );\n}<\/code><\/pre>\n<p>Y, finalmente, dentro del m\u00e9todo de representaci\u00f3n 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 \u00edcono en el bot\u00f3n de arriba. Agregamos dos bloques de salida, uno si <code>this.state.editMode<\/code>es <code>true<\/code>(que deber\u00edan ser los <code>RichText<\/code>componentes editables habituales) y otro si es <code>false<\/code>.<\/p>\n<p>Como ejemplo, estoy usando dos componentes de WordPress de <code>wp.components<\/code>; <code>Placeholder<\/code>y <code>Disabled<\/code>para el modo de vista previa. El <code>Placeholder<\/code>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\u00e9n envuelvo todo dentro de un <code>Disabled<\/code>componente que hace que todo el interior no se pueda editar, hacer clic ni arrastrar. Esta es nuestra nueva <code>render()<\/code>funci\u00f3n en nuestro componente:<\/p>\n<pre><code>const { ..., Fragment } = wp.element;\nconst {... Placeholder, Disabled } = wp.components;  \/\/ Don't forget to add these at the top\n\u00a0\n...\nrender() {\n    const { attributes, setAttributes } = this.props;\n    const alignmentClass = (attributes.textAlignment != null)? 'has-text-align-' + attributes.textAlignment: '';\n\u00a0\n    return ([\n        this.getInspectorControls(),\n        this.getBlockControls(),\n        &lt;div className={alignmentClass}&gt;\n            {this.state.editMode &amp;&amp; \n                &lt;Fragment&gt;\n                    &lt;RichText \n                        tagName=\"h2\"\n                        placeholder=\"Write your heading here\"\n                        value={attributes.myRichHeading}\n                        onChange={(newtext) =&gt; setAttributes({ myRichHeading: newtext })}\n                    \/&gt;\n                    &lt;RichText\n                        tagName=\"p\"\n                        placeholder=\"Write your paragraph here\"\n                        value={attributes.myRichText}\n                        onChange={(newtext) =&gt; setAttributes({ myRichText: newtext })}\n                    \/&gt;\n                &lt;\/Fragment&gt;\n            }\n            {!this.state.editMode &amp;&amp; \n                &lt;Placeholder isColumnLayout={true}&gt;\n                    &lt;Disabled&gt;\n                        &lt;RichText.Content \n                            tagName=\"h2\"\n                            value={attributes.myRichHeading}\n                        \/&gt;\n                        &lt;RichText.Content\n                            tagName=\"p\"\n                            value={attributes.myRichText}\n                        \/&gt;\n                    &lt;\/Disabled&gt;\n                &lt;\/Placeholder&gt;\n            }\n        &lt;\/div&gt;\n    ]);\n}\n...<\/code><\/pre>\n<p>Tambi\u00e9n estoy usando un componente <code>Fragment<\/code>( <code>wp.element<\/code>paquete) que es el mismo que <code>React.Fragment<\/code>. Si no est\u00e1 familiarizado con \u00e9l, envolvemos la salida dentro de \u00e9l cuando no queremos agregar envoltorios HTML adicionales innecesarios. En React todo debe tener un nodo ra\u00edz. Cuando el modo de edici\u00f3n est\u00e1 activo (l\u00ednea <code>#13<\/code>), generamos dos <code>RichText<\/code>componentes uno detr\u00e1s del otro, por lo que necesitamos un nodo ra\u00edz alrededor de ellos.<\/p>\n<p>Cuando el modo de vista previa est\u00e1 activo (l\u00ednea <code>#29<\/code>), mostramos los <code>RichText<\/code>valores de los dos componentes. Como hacemos en <code>save<\/code>, usamos <code>RichText.Content<\/code>para devolver sus valores en lugar del peque\u00f1o editor.<\/p>\n<p>El componente <code>Placeholder<\/code>viene en estilo flexible y por defecto con fila de direcci\u00f3n flexible. Proporcionar <code>true<\/code>en el accesorio <code>isColumnLayout<\/code>lo cambia a una columna de direcci\u00f3n flexible (para que todo se apila). Pero como se mencion\u00f3 anteriormente, es posible que desee omitir este componente y generar su vista previa exactamente como lo har\u00eda en la interfaz.<\/p>\n<p>Y con eso tenemos un conmutador de vista previa\/edici\u00f3n del modo de bloque. Obviamente, puede ajustar el contenido del &quot;modo de edici\u00f3n&quot; para mostrar, por ejemplo, entradas de control o lo que sea.<\/p>\n<\/p>\n<p>Puede crear tantos componentes como desee, \u00a1no est\u00e1 limitado a tener solo uno para la <code>edit<\/code>funci\u00f3n! Simplemente cree m\u00e1s componentes e incl\u00fayalos dentro de una <code>return<\/code>declaraci\u00f3n. Esa es la idea de React, en realidad: construir piezas de c\u00f3digo encapsuladas, posiblemente cada una manejando su propio estado y combin\u00e1ndolas para crear interfaces de usuario complejas.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>En esta parte de nuestro tutorial de bloques de Gutenberg, aprenderemos c\u00f3mo mover la funci\u00f3n de edici\u00f3n de registerBlockType a un componente separado basado en clases.<\/p>\n","protected":false},"author":1,"featured_media":152941,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[892,892,716,716,831,935,935,1110,800,800,831,840,840,861,861],"tags":[1172],"class_list":["post-233536","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-desarrollador","category-guia-para-principiantes","category-gutenberg-2","category-n-a","category-php-2","category-tutoriales","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/233536","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=233536"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/233536\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/152941"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=233536"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=233536"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=233536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}