Angular 2 | Conceptos previos, parte 4

Introducción a ES6

ES6, ECMAScript 6 o ES2015 es el standar de Javascript vigente a partir del 2015. En la actualidad hay mayor soporte por parte de algunos navegadores, pero aún el soporte no es total, por este motivo existen los transpiladores, que se encargan de convertir el código ES6 al estándar anterior.

Novedades

let

Permite declarar variables y limitar su alcance al bloque donde fué declarada.

Las diferencias con var son que esta última tiene como alcance su función contenedora y no es elevada a la parte superior del bloque (var si lo hace).

const

Esto es para declaración de contantes.

Objetos

Se introduce una mejora o atajo en la creación de objetos cuando la propiedad tiene el mismo nombre que la variable usada como valor.

ES5

ES6

Asignación desestructurada

Es un atajo para asignar variables desde objetos o arrays.

ES5

ES6

Ejemplo con array

Parámetros por defecto

Permite llama a una función con cualquier cantidad de argumentos, si se pasan más argumentos que los declarados, los sobrantes se ignoran, si se pasan menos, éstos serán seteados como undefined.

La definición de parámetros por defectos es como en cualquier lenguaje, podemos destacar que el valor por defecto puede ser una función:

Operador rest

Lo que hace es recoger múltiples elementos y los condensa en uno solo. En ES5 lo podemos hacer con la variable arguments, pero es ES6 lo declaramos nosotros explicitamente.

De forma similar se puede usar el operador de propagación (spread) que hace lo opuesto al rest, toma un array y lo descompone en N variables. Puede ser confundido ya que la sintaxis es la misma:

OOP

Se incorpora orientación a objetos nativa, clases, herencia, métodos estáticos, etc, etc…

Promises

Simplifican la programación asíncrona, no es una nueva funcionalidad como tal, sino que se reestructura la forma de hacerlo, que más sencillo de leer.

En ES5 tenemos que usar callbacks, ir llamando a funciones luego de que termina un llamado asíncrono.

En ES6, con las promises quedaría así:

Las promises son objetos de la clase Promise, la cual recibe 2 argumentos, un callback en caso de éxito, y otro en caso de fallo.

Otra cosa útil que tiene este objeto es el manejo de errores, en este ejemplo lo declaramos particular por cada promesa:

En este ejemplo lo declaramos general para toda la cadena de promesas, cualquiera que falle irá al catch:

Arrow functions

Recibe el nombre por su sintaxis:

Como vemos, si el argumento es único podemos enviarlo sin parentesis, en caso de que haya más de uno tendremos que usarlos. Otra cosa opcional es el bloque de código en el caso de que sea una operación simple, caso contrario deberemos usarlo. También podríamos declarar una función sin parámetros con los paréntesis vacios.

Lo que logramos en cualquiera de los casos es declarar una función que luego la podemos invocar de la forma que estamos acostumbrados:

Más allá de simplificar el código, hay un uso funcional, y es el de tener un mejor control del this, por ejemplo:

El error se debe a que estamos intentando acceder al método doSomething del objeto, pero en ese ámbito, this está haciendo referencia a document, por lo que el método buscado no existe.

Una solución podría ser bindear (ligar, asociar) el this de la función al this actual, que en este caso es el del pageHandler.

Esto lo podemos resolver mejor con las arrow functions, el valor de this dentro de estas funciones es igual al entorno donde fueron definidas. Por lo que, en el ejemplo, vemos que es definida dentro del pageHandler.

Hay ciertos casos donde no debemos usar estas funciones:

1 -Cuando se necesite acceder a argumentos dinámicos, ya que las arrow functions no exponen el objeto arguments:

2- Uso como método. Sabemos que los métodos son funciones que están asociadas a un objeto, y dependen del valor correcto de this para poder hacer su trabajo.

3- Uso como constructor

4- En funciones generador (nuevo tipo de funciones), ya que la palabra clave yield (de la que se valen estas funciones) no está permitida en funciones arrow.

Template literals

Podemos usar una sintaxis dentro de comillas invertidas ( ` ) para concatenar variables.

ES5

ES6

Estas comillas también nos permiten usar strings multilinea:

ES5

ES6

Módulos

Se incorpora de forma nativa (en ES5 se podía hacer con RequireJS por ejemplo) la organización de funcionalidades en módulos.

A través de export exponer librerías, funciones o valores y con import podemos incluirlos donde necesitemos.

races_service.js

app.js

Podemos usar alias al importar, y un wilcard (*) para importar todo lo que contiene el archivo:

Con esto terminamos la introducción a Angular intentando refrescar y reforzar conceptos que quizá ya dominaban o incluso desconocían.

Angular 2 | Conceptos previos, parte 3

Estructura de carpetas

/src/

Donde se ubica el código fuente del proyecto, puntualmente dentro de la carpeta app es donde se programa la aplicación.

Hay que recordar que al desplegar el proyecto, los archivos se compilan y se llevan a la carpeta dist, donde por ejemplo no se encontrarán los archivos .ts (recordar que estos se usan en etapa de desarrollo)

/dist/

Acá se ubicará la versión a subir al servidor público.

/Public/

Archivos estáticos, assets.

/e2e/

Para las pruebas. Viene de “end to end” testing.

/node_modules/

Archivos de las dependencias declaradas en package.json

/tmp/

Archivos temporales de Angular CLI

Typings

Como vimos, Typescript añade funcionalidades a Javascript, entre ellas, el tipado. Esta característica le permite al compilador checkear que las operaciones con las variables declaradas sean las permitidas / esperadas.

Se pueden usar tipos tanto para asignación como para retorno de métodos, como cualquier lenguaje fuertemente tipado. Luego de la transpilación, esto desaparece como tal, y es convertido en código Javascript para que se mantengan estas validaciones de tipos.

TypeScript

Como dijimos, Typescript es un superset de ES6 (ver link), por lo que a todo lo que éste trae, le agrega nuevas cosas y la principal es el tipado (de ahí el nombre) estático.

Por esta característica de ser un superset, podemos usar ES6 estándar mezclado con Typescript y el transpilador se encargará de transformar todo eso en ES5 sin problemas.

Tipos

Volviendo a los tipos, Javascript es de tipado dinámico, lo que quiere decir es que podríamos hacer algo así sin problemas:

¿Pero qué pasaría si esta variable la debemos enviar a un método que necesita operar sobre un número? Veamos:

Javascript

Typescript

En Javascript obtendríamos un solo error y en tiempo de ejecución por intentar iterar sobre un número.

En cambio, en Typescript obtendríamos 2 errores y en tiempo de compilación, el primero al intentar asignar un string a un array (error de código a propósito) y el segundo error es por el tipo de parámetro esperado por el constructor.

La sintaxis básica es:

Y también podemos usarla para definir tipos de retorno de una función:

Otra ventaja de los tipos es que al trabajar con otras librerías no sabemos que tipos de parámetros debemos usar, para esto, la comunidad usa archivos especiales que contienen la interfaz (nosotros deberíamos hacerlo también), por convención tienen la extensión .d.ts.

Podemos ir a https://github.com/DefinitelyTyped/DefinitelyTyped para ver un listado de posibles tipos a usar y luego agregarlo como dependencia de desarrollo en nuestro package.json:

OOP

Podemos usar todo lo relacionado con OOP, veamos un ejemplo:

Decoradores

Es un patrón de diseño que permite agregar funcionalidades a un objeto (métodos, clases, funciones, etc) de forma dinámica a través de otra función, todo esto sin modificar la original.

Puede ser usado, por ejemplo, para alterar los parámetros de llamada, llamar a otros métodos cuando el objeto es llamado, agregar metadata para un framework (esto hace Angular2).

Los decoradores empiezan con un @ y pueden ser aplicados a clases, propiedades de clases, funciones o parámetros. Pero no pueden ser aplicadas a un constructor.

Por ejemplo, necesitamos loguear cada vez que es llamado un método:

Con Angular2 usaremos mucho este concepto, ya que el framework se vale del mismo para enviar metadata de sus componentes.

Algunos términos

ReactJS

Proyecto de Facebook para la implementación de componentes web

EmberJS

Podríamos verlo como una alternativa a AngularJS, un framework MVC para desarrollar aplicaciones del lado del cliente.

Traceur

Es un compilador, permite llevar código ES6 y lo lleva a ES5 (o versión de ES que indiquemos).

Babel

Idem Traceur.

Transpilar

Misma tarea que un compilador, pero parte de Typescript.

SystemJS

Es una librería encargada de cargar módulos de varios tipos: ES6, AMD, CommonJS, scripts globales de cliente y servidor (Node). Le indicamos donde se encuentran los módulos necesarios y se encarga automáticamente de descargar las dependencias de nuestra aplicación.

Esto funciona bien en desarrollo, pero en producción tendríamos muchisimas descargas de pequeños módulos, la librería cuenta con una herramienta para empaquetar varios módulos en uno.

Webpack

Alternativa a SystemJS.

Yeoman

Es un generador de estructura de proyectos a través de línea de comandos, tiene una gran cantidad de posibles generadores, entre ellos obviamente Angular.

Angular 2 | Conceptos previos, parte 2

Archivos de configuración

package.json

Configuración de detalle de dependencias del proyecto.

tsconfig.json

Directivas para el compilador Typescript.

systemjs.config.js

Información utilizada por el loader para saber donde encontrar los módulos requeridos.

Podemos crear y modificar estos archivos a mano, pero veremos como optimizar todo este proceso mediante Angular CLI.

Con el siguiente comando podemos crear el package.json, nos pedirá algo de info para inicializarlo

Luego podemos ir agregando dependencias, tanto en nuestro proyecto (descarga de archivos fisicos) como en el archivo de configuración con el siguiente comando

Lo importante de la sentencia anterior es que podemos incluir la cantidad de dependencias que querramos, para saber cuáles necesitaríamos podemos ir a https://angular.io/docs/ts/latest/guide/npm-packages.html#!#dependencies y el modificador –save lo que hace es agregar las dependencias instaladas al package.json

Angular CLI

Intérprete de línea de comandos incorporado en Angular que facilita el proceso de inicio de aplicaciones (estructura de carpetas, archivos, herramientas configuradas)

Instalación (el modificador -g indica que se instala de forma global)

Una vez instalador disponemos del comando “ng”, podemos encontrar la documentación acá: https://cli.angular.io/

Para crear un nuevo proyecto se usa

Esto creará una carpeta, y dentro la estructura inicial mencionada anteriormente. Algunas funcionalidades instaladas son:

  • Un servidor para servir el proyecto por HTTP
  • Un sistema de live-reload, para que cuando cambiamos archivos de la aplicación se refresque el navegador
  • Herramientas para testing
  • Herramientas para deploy

Vemos que esta estructura creada de forma automática, es la misma que creamos a mano en el apartado anterior para el archivo package.json.

Luego podemos entrar en el directorio creado y usar el comando serve para visualizar el proyecto sin necesidad de tener otro soft instalado (un servidor web por ejemplo)

Opcionalmente podemos indicarle el puerto en el que queremos que corra

Con un proyecto ya creado y configurado, para moverlo a otro servidor, podemos copiar todo salvo la carpeta node_modules y ejecutar $ npm install lo que creará dicha carpeta y descargará todas las dependencias declaradas en el package.json. Esto es muy útil, ya que dicha carpeta suele ser muy pesada.

Podemos valernos del CLI para crear el archivo de configuración de Typescript, por ejemplo

El listado de opciones lo encontramos en https://www.typescriptlang.org/docs/handbook/compiler-options.html

Podemos generar también el esqueleto de un componente:

Angular 2 | Conceptos previos, parte 1

Requisitos

  • Nodejs > 5.xx
  • NPM > 3.xx

Mejoras respecto a AngularJS

Implementación de

  • Components
    • Es la arquitectura de una aplicación Angular 2, es obligatorio (en la versión 1.5 de Angular se podía usar pero de forma opcional)
    • Se puede llegar a comparar con las directivas 
    • Estan compuestos por
      • Templates
        • Trozos HTML
      • Custom elements
        • Son templates más complejos, no solo contienen HTML sino que incorporan otras funcionalidades
      • Shadow DOM
        • Entorno (sandbox) que encapsula reglas CSS y Javascript
      • HTML imports
        • Permite el acceso a otros documentos HTML no albergados
  • Data binding flow
    • Optimización del data binding, el tiempo de procesamiento puede ser hasta 5 veces más rápido
    • El flujo de datos puede ser direccionado facilmente por el desarrollador
  • Renderizado universal
    • Permite renderizado del lado del servidor, muy importante para SEO
      • Recordar que en AngularJS el renderizado era en el cliente y esto dificultaba el SEO
    • Permite renderizar en otro lenguaje nativo para un dispositivo dado
  • Dependency injection: Lazy SPA
    • Permite cargar código (clases, etc) a medida que se necesiten
    • No se cargan todas las dependencias en memoria
  • ECMAscript 2015 / 6
    • Declaración de variables let
    • Declaración de constantes
    • Mejora en declaración de objetos
    • Asignación desestructurada
    • Parámetros por defecto
    • Operador rest / spread (…)
    • Clases (OOP)
    • Promises
    • Funciones flecha (arrow functions)
    • Templates de cadenas de texto (literals)
    • El Javascript que utilizamos actualmente es conocido como ES5, ES6 agrega nuevas funcionalidades, aunque aún no es un estándar soportado por los navegadores
    • Algunas características son (las veremos en detalle luego)
  • TypeScript (un paso más allá de ES6)
    • Lenguaje de alto nivel que implementa OOP, compila en Javascript nativo (transpilación => “translate” + “compiler” = “transpiler”). Por esto se dice que es un superset de ES6, un lenguaje escrito encima de otro.
    • Es utilizado en etapa de desarrollo, el código que se ejecuta en el navegador es Javascript.
    • Permite detectar errores en tiempo de compilación y en consecuencia reducir errores en tiempo de ejecución.