Un framework para aplicaciones ambiciosas

Luis Mendoza | @luismendozamx
ChelaJS | 13 de enero 2016

¿Por qué tantos frameworks JS?

Hola

Un poco de historia

Originalmente SproutCore 2.0

Creado por Yehuda Katz y Tom Dale en 2011

Principios de Diseño

Antes MVC, ahora MRCC*

Centrado en el URL

Convention Over Configuration

* MRCC es un término mío, no es oficial

De
MVC: Modelo - Vista - Controlador
a
MRCC: Modelo - Ruta - Controlador - Componente

MVC: Modelo - Vista - Controlador

Problema: Se volvio complejo y difícil de escalar.

MVC: Modelo - Vista - Controlador

Modelo: Representación de datos

Ruta: Cargar modelo, vista y controlador

Template: Definición de markup

Controlador: Conexión entre datos y template

Vista: Conexión al DOM y manejo de eventos

MRCC: Modelo - Ruta - Controlador - Componente

Influencia de React y Web Components

MRCC: Modelo - Ruta - Controlador - Componente

Ventajas: Reutilizable, aislado, menos redundate, menos confuso, más fácil de mantener.

Modelo - Ruta - Controlador - Componente

El Ecosistema de Ember.js

ember-data

ember-cli

ember-inspector

ember-cli

Utilidad de línea de comandos para el desarrollo


$ ember new todo-app
$ ember generate model todo
$ ember serve
$ ember build

ember-data

Utilizada para manejar la información y estado de los modelos.


// Model
const todo = DS.Model.extend({
  title: DS.attr('string'),
  completed: DS.attr('booolean')
});

// Store
this.store.findAll('todo');

Arquitectura de Ember

Router

Modelos

Rutas

Controladores

Templates

Componentes

Router

/todos

/todos/new

/todos/:todo_id


Router.map(function() {
  this.route('todos', function() {
    this.route('new', { path: '/new' });
    this.route('show', {path: '/:todo_id'});
  });
});

Modelos


// models/todo.js
import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  completed: DS.attr('boolean'),
  description: DS.attr('string'),

  list: DS.belongsTo('list')
});

Ruta


// routes/todos/index.js
import Ember from 'ember';

export default Ember.Route.extend({
  model() {
    return this.store.findAll('todo');
    // alternativamente: return $.getJSON('...') o $.ajax('...');
  },

  beforeModel() { /* código ejecutado antes de resolver el modelo */ },

  actions: {
    updateTodo(todo) {
      todo.save();
    }
  }
});

Controlador

/todos?page=1&sort=createdAt


// controllers/todos/index.js
import Ember from 'ember';

export default Ember.Controller.extend({
  queryParams: ['page', 'sort'],
  page: 1,
  sort: 'createdAt',
  asc: false,

  actions: {
    toggleSortDirection() {
      this.toggleProperty('asc');
    }
  }
});

Templates


{{! templates/todos/index.hbs }}

{{#each model as |todo|}}
  <‍div>
    <‍p>{{todo.title}}<‍/p>
  <‍/div>
{{/each}}

Componentes


// components/add-todo-form.js
import Ember from 'ember';

export default Ember.Component.extend({
  todo: null,

  actions: {
    saveTodo(todo) {
      this.sendAction('saveTodo', todo);
    }
  }
});

Componentes


{{! templates/components/add-todo-form.hbs }}

<‍form {{action 'saveTodo' todo on='submit'}}>
  {{input value=todo.title}}
<‍/form>

Componentes


{{! templates/todos/new.hbs }}
{{add-todo-form todo=model saveTodo='saveTodo'}}

// routes/todos/new.js
...
model() {
 this.store.createRecord('todo', { completed: false });
},

actions: {
  saveTodo(todo) {
    todo.save().then(() => {
      // success
    }, () => {
      // error
    });
  }
}
...

Demo

Source: Cliente | API

¿Quién está usando Ember?

Conclusión

Poderoso y completo.

Fuertes convenciones.

Estable, buena comunidad y muy buena documentación.

Sigue las mejores prácticas y aprende de otros.

¡Gracias!

mendoza.io

github.com/luismendozamx

instagram.com/luismendozamx

twitter.com/luismendozamx