Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development
Code

Introducción al framework React

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

Hoy en día, en el mundo de frameworks JavaScript para aplicaciones, la filosofía es el factor clave que las diferencia. Si comparas los frameworks JS populares, como EmberJS, AngularJS, Backbone, Knockout, etc, seguramente encontrarás diferencias en sus abstracciones, modelos de pensamiento y, por supuesto, la terminología. Esto es una consecuencia directa de la filosofía de diseño subyacente. Pero, en principio, todos ellos hacen una cosa, que es abstraer el DOM en una forma que evite que tengas que tratar directamente con los elementos HTML.

Personalmente, creo que un framework se vuelve interesante cuando proporciona un conjunto de abstracciones que permiten un modo diferente de pensar. En este aspecto, React, el nuevo framework JavaScript de la gente de Facebook, te fuerza a replantear (hasta cierto punto) como descompones el UI y las interacciones de tu aplicación. Habiendo alcanzado la versión 0.4.1 (al momento de escribir este artículo), React proporciona un modelo sorprendentemente simple, pero eficaz, para la construcción de aplicaciones JavaScript que mezclan un delicioso cóctel de una manera distinta.

En este artículo, exploraremos los bloques de construcción de React y adoptaremos un estilo de pensamiento que puede parecer contra-intuitivo en un primer momento. Pero, como la documentación de React dice: "Dale cinco minutos" y entonces verás como este enfoque se vuelve más natural.

Motivaciones

La historia de React comienza dentro de los confines de Facebook, donde fue elaborado por un tiempo. Habiendo alcanzado un estado suficientemente estable, los desarrolladores decidieron lanzarlo como open source unos meses atrás. Es interesante que el sitio web de Instagram está desarrollado con React también.

React enfoca el problema de la abstracción del DOM con una visión ligeramente distinta. Para entender cómo esto es diferente, vamos a mirar rápidamente las técnicas adoptadas por los frameworks mencionados anteriormente.

Una mirada panorámica de los Frameworks JavaScript

El patron de diseño MVC (Modelo-Vista-Controlador) es fundamental para el desarrollo de UI, no solo en web apps, sino en aplicaciones front end en cualquier plataforma. En el caso de las web apps, el DOM es la representación física de una Vista. El DOM es generado desde una plantilla html que es extraída de un archivo diferente, bloque de script o una función precompilada de plantillas. La Vista es una entidad que trae la plantilla a la vida como un fragmento del DOM. También define los manejadores de eventos y cuida la manipulación del árbol DOM como una parte de su ciclo de vida.

Para que la Vista sea útil, necesita mostrar algunos datos y, posiblemente, permitir la interacción del usuario. Los datos son el Modelo, que viene de alguna fuente (una base de datos, un web service, local storage, etc). Los frameworks proporcionan una forma de "encadenar" los datos a la vista, de tal manera que los cambios en los datos sean automáticamente reflejados en cambios en la vista. Este proceso automático es llamado data-binding y hay APIs/técnicas para hacer esto lo más fluido posible.

La triada MVC es completada por el Controlador, que engancha la Vista y el Modelo y controla el flujo de los datos (Modelo) dentro de la Vista y los eventos de usuario fuera de la Vista, que pueden generar cambios en el Modelo.

mvc-flow

Los framworks que manejan automáticamente el flujo de datos hacia adelante y atrás entre la vista y el modelo mantienen un loop de eventos interno. Este loop de eventos es necesario para escuchar ciertos eventos de usuario, eventos de cambios de datos, disparadores externos, etc. y entonces determinar si hay algún cambio desde la ejecución anterior del loop. Si hay cambios, ya sea en la Vista o en el Modelo, el framework asegura que ambos sean devueltos sincronizados.

¿Qué hace a React diferente?

Con React, la parte de la vista en el modelo MVC se hace predominante y es envuelto dentro de una entidad llamada Componente. El componente mantiene una bolsa de propiedades inmutables llamada props y un state que representa el estado generado por el usuario de la UI. La parte de generación de vistas del component es bastante interesante y posiblemente la razón que hace a React destacar en comparación con otros frameworks. En vez de construir un DOM físico directamente desde el template/archivo/script/function, el component genera un DOM intermedio que es un sustituto del real DOM. Un paso adicional es realizado para traducir este DOM intermedio en el DOM real.

Como parte de la generación del DOM intermedio, el component adjunta manejadores de eventos y conecta los datos contenidos en props and state

Si la idea de un DOM intermedio suena un poco extraña, no te alarmes demasiado. Tu ya has visto esta estrategia adoptado por lenguajes en tiempos de ejecución (también conocidos como máquinas virtuales) para lenguajes interpretados. Primero, nuestra propia ejecución JavaScript, genera una representación intermedia antes de entregar el código nativo. Esto también es válido para otros lenguajes basados en VM (Vista, Modelo) como Java, C#, Ruby, Python, etc.

React inteligentemente adopta esta estrategia para crear un DOM intermedio antes de generar el DOM final. El DOM intermedio es solo un gráfico de objetos JavaScript y no es renderizado directamente. Hay un paso de traducción que crea el real DOM. Esta es la técnica subyacente que hace más veloces a las manipulaciones del DOM de React.

React en profundidad

Para tener una mejor imagen de como React hace todo el trabajo, vayamos un poco más en profundidad, comenzando con el component El componente es el bloque de construcción primario en React. Puede componer el UI de su aplicación ensamblando un arbol de componentes. Cada componente proporciona una implementacion para el método render(), donde es creado el DOM intermedio. Llamando a React.renderComponent() en la raíz de los resultados del componente en forma recursiva bajando por el árbol de componentes y construyendo el DOM intermedio. El DOM intermedio es entonces convertido en el real DOM HTML.

component-dom-tree

Desde que la creación del DOM intermedio es una parte integral del componente, React proporciona una conveniente extension para JavaScript basada en XML, llamada JSX, para construir el arbol de componentes como un set de nodos XML. Esto hace más fácil visualizar y razonar sobre el DOM. JSX también simplifica la asociación de manejadores de eventos y propiedades como atributes XML. Desde que JSX es una extensión del lenguaje, hay una herramienta (en linea de comandos y navegador) para generar el JavaScript final. Un nodo JSX XML mapea directamente a un Componente. Vale la pena señalar que React trabaja idependientemente de JSX y el lenguaje JSX solo hace que sea fácil crear el DOM intermedio.

Tooling

El core de React puede ser descargado desde su sitio web. Adicionalmente, para la transformación de JSX a JS puedes elegir la herramienta JSXTransformer para el navegador o usar react-tools (una herramienta en línea de comandos que se instala via NPM). Necesitarás una instalación de Node.js para descargarlo. La herramienta en línea de comandos te permite precompilar los archivos JSX e impedir la traducción dentro del navegador. Esto es definitivamente recomendado si tu archivos JSX son largos o son muchos.

Un simple componente

Bien, hemos visto un montón de teoría hasta ahora, y estoy seguro que tienes ganas de ver algo de código real. Vamos a nuestro primer ejemplo:

Aunque simple, el código anterior cubre mucho de React:

  • Creamos el componente Simple utilizando React.createClass y pasando un objeto que implementa algunas funciones principales. El más importante es render(), que genera el DOM intermedio.
  • Aquí estamos usando JSX para definir el DOM y también adjuntamos el controlador de eventos mousedown. La sintaxis {} es útil para incorporar expresiones JavaScript para atributos (onMouseDown = {this.handleClick}) Y los nodos hijos (<span class="count">{this.state.count}></span>) Los controladores de eventos asociados mediante la sintaxis {} se enlazan automáticamente a la instancia del componente. Por lo tanto, this dentro de la función del controlador de eventos se refiere a la instancia de componente. El comentario en la primera línea /** @jsx React.DOM */ es una señal para que el transformador JSX realice la traducción a JS. Sin esta línea de comentario, no habrá traducción.

Podemos ejecutar la herramienta de línea de comandos (jsx) en modo watch y auto-compilar los cambios de JSX → JS. Los archivos de codigo se encuentran en la carpeta /src y la salida se genera en /build.

Este es el archivo JS generado:

Observe cómo las etiquetas <div/> y <span/> se asignan a instancias de React.DOM.div y React.DOM.span.

  • Ahora volvamos a nuestro código de ejemplo. Dentro de handleMouseDown, hacemos uso de this.props para leer la propiedad del mensaje que se pasó. Establecemos el message en la última línea del fragmento, en la llamada a React.renderComponent() Donde creamos el componente <Simple/>. El propósito de this.props es almacenar los datos que se pasaron al componente. Se considera inmutable y sólo un componente de nivel superior se le permite hacer cambios y pasarlo a el árbol de componentes.
  • Dentro de handleMouseDown también establecemos algún estado de usuario con this.setState() para rastrear el número de veces que se mostró el mensaje. Notarás que usamos this.state en el método render(). Cada vez que llame a setState(), React también activa el método render() para mantener el DOM sincronizado. Además de React.renderComponent(), setState() es otra forma de forzar una actualización visual.

Eventos sintéticos

Los eventos expuestos en el DOM intermedio, como el onMouseDown, también actúan como una capa de indirección antes de que se establezcan en el DOM real. Estos sucesos se denominan eventos sintéticos. React adopta la delegación de eventos, que es una técnica bien conocida, y asigna eventos sólo al nivel raíz del DOM real. Por lo tanto, sólo hay un verdadero controlador de eventos en el DOM real. Además, estos eventos sintéticos también proporcionan un nivel de coherencia al ocultar las diferencias de navegador y elementos.

La combinación del DOM intermedio y los eventos sintéticos le ofrece una forma estándar y consistente de definir las interfaces de usuario a través de diferentes navegadores e incluso dispositivos.

Ciclo de vida del componente

Los componentes del marco React tienen un ciclo de vida específico e incorporan una estado de máquina que tiene tres estados distintos.

component-lifecycle

El componente se ejecuta después de ser montado. El montaje resulta en pasar a través de una representacion que genera el árbol de componentes (DOM intermedio). Este árbol se convierte y se coloca en un contenedor-nodo del DOM real. Esto es un resultado directo de la llamada a React.renderComponent().

Una vez montado, el componente permanece en el estado de actualización. Un componente se actualiza cuando cambia el estado usando setState() o cambia los apoyos usando setProps(). Esto a su vez resulta en llamar render(), lo que sincroniza el DOM con los datos (props + state). Entre actualizaciones posteriores, React calculará el delta entre el árbol de componentes anterior y el árbol recién generado. Este es un paso altamente optimizado (y una característica insignia) que minimiza la manipulación en el DOM real.

El estado final es Unmounted. Esto ocurre cuando se llama explícitamente a React.unmountAndReleaseReactRootNode() o automáticamente si un componente era un hijo que ya no se generaba en una llamada render(). La mayoría de las veces no tienes que lidiar con esto y debes dejar que React haga lo correcto.

Ahora habría sido un gran descuido, si React no te dijo cuándo se movió entre los estados Mounted-Update-Unmounted . Afortunadamente que no es el caso y hay hooks que pueden anular el ser notificado de los cambios en el ciclo de vida. Los nombres hablan por sí mismos:

  • GetInitialState(): prepara el estado inicial del componente
  • componentWillMount()
  • componentDidMount()
  • componentWillReceiveProps()
  • ShouldComponentUpdate(): útil si desea controlar cuándo debe omitirse un render.
  • componentWillUpdate()
  • render()
  • componentDidUpdate()
  • componentWillUnmount()

Los métodos componentWill* se llaman antes del cambio de estado y los métodos componentDid* se llaman después.

Algunos de los nombres de métodos parecen haberse tomado de los marcos Cocoa en Mac e iOS

Otras características

Dentro de un árbol de componentes, los datos siempre deben fluir hacia abajo. Un componente padre debe establecer props de un componente hijo para pasar cualquier dato del padre al niño. Esto se denomina como el par propietario-propiedad. Por otro lado, los eventos de usuario (ratón, teclado, toques) siempre burbujearán desde el niño hasta el componente raíz, a menos que se maneje entre ellos.

data-event-flow

Cuando crea el DOM intermedio en render(), también puede asignar una propiedad ref a un componente secundario. A continuación, puede referirse a él desde el padre utilizando la propiedad refs. Esto se muestra en el siguiente fragmento.

Como parte de los metadatos del componente, puede establecer el estado inicial (getInitialState()), que vimos anteriormente dentro de los métodos del ciclo de vida. También puede establecer los valores predeterminados de los apoyos con getDefaultProps() y también establecer algunas reglas de validación en estos apoyos mediante propTypes. Los documentos dan una buena visión general de los diferentes tipos de validaciones (verificaciones de tipo, necesarias, etc.) que puede realizar.

React también apoya el concepto de un Mixin para extraer piezas reutilizables de comportamiento que se pueden inyectar en Componentes dispares. Puede pasar los mixins usando la propiedad mixins de un componente.

Ahora, vamos a ser real y construir un componente más completo que utiliza estas características.

Un Editor de Formas Construido Utilizando React

En este ejemplo, crearemos un editor que acepte un simple DSL (Domain Specific Language) para crear formas. A medida que escribe, verá la salida correspondiente en el lado, dándole comentarios en vivo.

La DSL le permite crear tres tipos de formas: Elipse, Rectángulo y Texto. Cada forma se especifica en una línea separada junto con un montón de propiedades de estilo. La sintaxis es sencilla y toma un poco de CSS. Para analizar una línea, usamos un Regex como el siguiente:

Como ejemplo, el siguiente conjunto de líneas describe dos rectángulos y una etiqueta de texto...

... generando la salida que se muestra a continuación:

react-shapes

Configuración

Muy bien, vamos a seguir adelante y construir este editor. Comenzaremos con el archivo HTML (index.html), Donde ponemos el marcado de nivel superior e incluimos las bibliotecas y los scripts de la aplicación. Solo estoy mostrando las partes relevantes aquí:

En el fragmento anterior, la div container contiene nuestro DOM generado por React. Nuestros scripts de la aplicación se incluyen en el directorio /build. Estamos utilizando JSX dentro de nuestros componentes y el observador de línea de comandos (jsx), pone los archivos JS convertidos en /build. Tenga en cuenta que este comando watcher forma parte del módulo NPM react-tools.

El editor se descompone en un conjunto de componentes, que se enumeran a continuación:

  • ShapeEditor: el componente raíz en el árbol de componentes
  • ShapeCanvas: responsable de generar los componentes de forma (Elipse, Rectángulo, Texto). Está contenido en el ShapeEditor.
  • ShapeParser: responsable de analizar el texto y extraer la lista de definiciones de forma. Analiza línea por línea con el Regex que vimos anteriormente. Las líneas no válidas se ignoran. Esto no es realmente un componente, sino un objeto JS de ayuda, utilizado por ShapeEditor.
  • Ellipse, Rectangle, Text: los Componentes de la forma . Estos se convierten en hijos de ShapeCanvas.
  • ShapePropertyMixin: proporciona funciones auxiliares para extraer los estilos que se encuentran en las definiciones de forma. Esto se mezcla en los tres componentes de forma utilizando la propiedad mixins.
  • App: el punto de entrada para el editor. Genera el componente raíz (ShapeEditor) y le permite seleccionar una muestra de forma en el menú desplegable.

La relación de estas entidades se muestra en el árbol de los componentes anotados:

component-tree

El componente ShapeEditor

Veamos la implementación de algunos de estos componentes, empezando por el ShapeEditor.

Como su nombre sugiere, ShapeEditor proporciona la experiencia de edición generando el <textarea /> y los comentarios en vivo en el <ShapeCanvas/> Escucha el evento onChange (los eventos en React siempre tienen el nombre de camel case) en la <textarea/> y en cada cambio, establece la propiedad text del state del componente. Como se mencionó anteriormente, siempre que establezca el estado mediante setState(), render se llama automáticamente. En este caso, el render() del ShapeEditor se llama donde analizamos el texto del estado y reconstruimos las formas. Tenga en cuenta que estamos empezando con un estado inicial de texto vacío, que se establece en el gancho getInitialState().

Para analizar el texto en un conjunto de formas, Utilizamos una instancia de ShapeParser. He dejado de lado los detalles del analizador para mantener la discusión enfocada en React. La instancia del analizador se crea en el gancho componentWillMount(). Esto se llama justo antes de que el componente se monta y es un buen lugar para hacer cualquier inicialización antes de que se produzca la primera.

Por lo general, se recomienda que realice todo el procesamiento complejo a través del método render(). Los controladores de eventos sólo configuran el estado mientras render() es el concentrador de toda la lógica del núcleo.

El ShapeEditor utiliza esta idea para hacer el análisis dentro de su render() y reenvía las formas detectadas estableciendo la propiedad shapes de ShapeCanvas. Así es como los datos fluyen hacia abajo en el árbol de componentes, desde el propietario (ShapeEditor) hasta el propiedad (ShapeCanvas).

Una última cosa a tener en cuenta aquí es que tenemos el primer comentario de línea para indicar traducción JSX → JS.

ShapeCanvas para generar las formas

A continuación, pasaremos a ShapeCanvas los componentes Elipse, Rectángulo y Texto.

El ShapeCanvas es bastante sencillo con su responsabilidad principal de generar los respectivos componentes <Ellipse/>, <Rectangle/> y <Text/> de las definiciones de forma pasadas (this.props.shapes). Para cada forma, pasamos las propiedades analizadas con la expresión de atributo: properties={shape.properties}.

Una cosa diferente aquí es que nuestro árbol de componentes no es estático, como lo hemos hecho en ShapeEditor. En su lugar, se genera dinámicamente al realizar bucle sobre las formas pasadas. También mostramos el mensaje "No hay formas encontradas" si no hay nada que mostrar.

Las Formas: Elipse, Rectángulo, Texto

Todas las formas tienen una estructura similar y difieren sólo en el estilo. También hacen uso de la ShapePropertyMixin para manejar la generación de estilo.

Aquí está Elipse:

La implementación de extractStyle() es proporcionada por ShapePropertyMixin.

El componente de rectángulo sigue el juego, por supuesto sin el estilo border-radius. El componente Text tiene una propiedad extra llamada value que establece el texto interno para el <div/>.

Aquí está Text, para dejar esto claro:

Uniendo todo junto en App.js

App.js es donde lo ponemos todo junto. Aquí hacemos que el componente raíz, el ShapeEditor y también proporcionar apoyo para cambiar entre algunas formas de muestra. Cuando selecciona una muestra diferente de la lista desplegable, cargamos algún texto predefinido en ShapeEditor y hacemos que ShapeCanvas se actualice. Esto sucede en el método readShapes().

Para ejercitar el lado creativo, aquí está un robot construido usando el Shape Editor:

robot

¡Y eso es React!

¡Uf! Este ha sido un artículo bastante largo y habiendo llegado a este punto, usted debe tener un sentido de logro!

Hemos explorado una gran cantidad de conceptos aquí: el papel integral de los componentes en el marco, el uso de JSX para describir fácilmente un árbol componente (aka intermedio-DOM), varios ganchos para conectar en el ciclo de vida del componente, el uso del state y props para manejar El procesamiento, el uso de Mixins para factorizar el comportamiento reutilizable y finalmente tirar todo esto junto con el ejemplo del Editor de formas.

Espero que este artículo le da suficiente impulso para construir algunas aplicaciones React para ti. Para continuar su exploración, aquí hay algunos enlaces útiles:

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.