Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ember.js. Aplicaciones complejas en el cliente

89e3039f1a0c7d1733b3b6054d042709?s=47 Pepe Cano
April 27, 2012

Ember.js. Aplicaciones complejas en el cliente

Introducción a Ember.js

89e3039f1a0c7d1733b3b6054d042709?s=128

Pepe Cano

April 27, 2012
Tweet

More Decks by Pepe Cano

Other Decks in Programming

Transcript

  1. None
  2. Contexto - Motivación

  3. Usando múltiples dispositivos

  4. Futuro - Ubiquitous Computing https://vimeo.com/31239358?t=3m45s

  5. "It's like you build something and people experience it in

    all these different places. So making it so you can build once and kind of have it in a lot of these different places I think it's going to be very valuable." Mark Zuckerberg (CEO de Facebook), Octubre 2010.
  6. Problemas

  7. Solución MULTIMEDIA PERFORMANCE & INTEGRATION 3 GRAPHICS, EFFECTS CSS3 STYLING

  8. Solución DEVICE ACCES HTML SEMANTICS OFFLINE & STORAGE CONNECTIVITY

  9. "We can do 95 percent of what we want to

    do with HTML5" Thom Cummings (VP marketing de Soundcloud), Febrero 2012.
  10. Historia / Tendencia Aplicaciones Web Aplicaciones de escritorio WebApps Apps

  11. Evolución de la Web

  12. "This is the best time ever to be a software

    developer" Steve Ballmer (CEO de Microsoft), Septiembre 2011.
  13. Ember.js

  14. Ember.js JavaScript framework for creating ambitious web applications that eliminates

    boilerplate and provides a standard application architecture
  15. Frameworks MVC JS Bindings Plantillas HTML Vistas jerárquicas Interoperabilidad Backbone.js

    Spine.js Knockout.js Batman.js Serenade.js Angular.js Ember.js Sproutcore > 1.5 Cappuchino Thanks to @tchak13
  16. Historia Incluir lo mínimo y añadir según necesidad Facilitar la

    integración de aplicaciones existentes
  17. Arquitectura Modelos ( Dominio ) Estados Lógica App Proxies -

    ( Datos de la aplicación) Vistas
  18. Computed, bindings y observers Person = Ember.Object.extend({ firstName: null, lastName:

    null, fullName: function() { return this.get(' firstName') + ' ' + this.get(' lastName'); }.property('firstName', 'lastName'), fullNameChanged: function() { //do whatever u want }.observes('fullName') }); App.selectedBrandsController = Em.ArrayController.create({ content: null, selectedCategory Binding: Em.Binding.oneWay('App. categoryController.selectedItem') }); Mantiene una lista de sus dependientes y notifica de los cambios
  19. Arquitectura Modelos ( Dominio ) Estados Lógica App Proxies -

    ( Datos de la aplicación) Vistas
  20. Modelos Define el esquema del dominio y contiene los datos

    persistentes App.Brand = DS.Model.extend({ name: DS.attr('string'), marked: DS.attr('boolean') });
  21. Modelos - Ember Data Ember-data (ORM en el lado del

    cliente) para REST API • Define relaciones ( hasMany, hasOne, belongsTo ) • Query ( find, findQuery, findAll ) • Create, update, delete • Backend independiente
  22. Arquitectura Modelos ( Dominio ) Estados Lógica App Proxies -

    ( Datos de la aplicación) Vistas
  23. Proxies user1 user2 user3 UserController UserListView FriendsView

  24. Proxies App.selectedUser = Em.Object.create({ content: null, hasBeenVisited: false }); App.arrayItemController

    = Em.ArrayController.create({ content: null, remaining: function() { var content = this.get('content'); return content.filterProperty('isDone',false).get('length'); }.property('content.@each.isDone') });
  25. Arquitectura Modelos ( Dominio ) Estados Lógica App Proxies -

    ( Datos de la aplicación) Vistas
  26. Coordinadores (ember-states) Gestiona los distintos estados y eventos del usuario/aplicación

    • StateManager ( define los estados ) • States ( send, goToState ) start search home result if X else
  27. Arquitectura Modelos ( Dominio ) Estados Lógica App Proxies -

    ( Datos de la aplicación) Vistas
  28. Vistas Gestiona la representacion de los datos y eventos del

    usuario App.coolView = Ember.View.create({ render: function(buffer) { buffer.push("<b>This view is so cool!</b>"); } }); my_view.js App.myView = Em.View.create({ userBinding: Em.Binding.oneWay(‘App.userController.content’), templateName: ‘my_view’ }); my_view.handlebars {{#if user}} Welcome back, <b>{{user.firstName}} {{user.lastName}}</b>! {{view App.LanguageIconView contentBinding="user.language" }} {{/if}}
  29. Vistas view.appendTo('#container'); view.remove(); var view = Em.ContainerView.create({ childViews: [‘label’, ‘input’,

    ‘button’], label: App.LabelView, input: App.InputView, button: App.ButtonView });
  30. Ejemplo práctico

  31. Resultado <div id="category_list" class="ember-view"> <img class="ember-view category is-selected" src="category1.png" ></img>

    <img class="ember-view category" src="category2.png"></img> <img class="ember-view category" src="category3.png"></img> <img class="ember-view category" src="category4.png"></img> <img class="ember-view category" src="category5.png"></img> </div>
  32. Modelos models/category.js Yn.Category = DS.Model.extend({ name: DS.attr('string'), picture: DS.attr('string'), order:

    DS.attr('number') }); init/app.js var categories = Yn.store.find(Yn.Category, {order_by: 'order'});
  33. Proxies controllers/category.js App.categoriesController = Em.ArrayController.create({ content: null }); App.categoryController =

    Em.Object.create({ selectedItem: null }); init/app.js App.categoriesController.set('content', categories); App.categoryController.set('selectedItem', categories.get ('firstObject') );
  34. Vista de la lista de categorías views/category.js App.CategoryListView = Em.CollectionView.extend({

    elementId: ' category_list', contentBinding: Em.Binding.oneWay('App.categoriesController. content'), itemViewClass: App.CategoryView }); <div id="category_list" class="ember-view"> ... </div>
  35. Vista de la categoría App.CategoryView = Em.View.extend({ tagName: 'img', classNames:

    ['category'], attributeBindings: ['src'], src: Em.computed(function(){ return this.getPath('content.picture') ); }).property( 'content.picture') classNameBindings: ['is_selected'], selectedCategoryBinding: Em.Binding.oneWay(‘App. selectedCategory.content’), is_selected: Em.computed(function(){ return ( Em.getPath(this, 'selectedCategory.id') === this.getPath('content.id') ); }).property( 'content', 'selectedCategory') }); <img class="ember-view category is-selected" src="category1.png" ></img>
  36. Eventos de usuario views/category.js App.CategoryView = Em.View.extend(App.bTap, { .... bTap:

    function(){ App.manager.send(' selectedCategory ', this.get(' content') ); } }); states/category.js App.CategoryState = Em.State.extend({ selectedCategory: function( stateManager, category ) { App.categoryController.set('selectedItem', category); } });
  37. Resultado <div id="category_list" class="ember-view"> <img class="ember-view category" src="category1.png"></img> <img class="ember-view

    category" src="category2.png"></img> <img class="ember-view category is-selected" src="category3.png" ></img> <img class="ember-view category" src="category4.png"></img> <img class="ember-view category" src="category5.png"></img> </div>
  38. Vista de la categoría App.CategoryView = Em.View.extend({ tagName: 'img', classNames:

    ['category'], attributeBindings: ['src'], src: Em.computed(function(){ return this.getPath('content.picture') ); }).property( 'content.picture') classNameBindings: ['is_selected'], selectedCategoryBinding: Em.Binding.oneWay(‘App. selectedCategory.content’), is_selected: Em.computed(function(){ return ( Em.getPath(this, 'selectedCategory.id') === this.getPath('content.id') ); }).property( 'content', 'selectedCategory') }); <img class="ember-view category is-selected" src="category1.png" ></img>
  39. Arquitectura Modelos ( Dominio ) Estados Lógica App Proxies -

    ( Datos de la aplicación) Vistas
  40. Destacando

  41. Definiendo vistas Yn.ActionButtonView = Em.ContainerView.extend(Yn.Btap, {..}); "Each rule set that

    we add to our style sheet creates an ever increasing connection between the CSS and the HTML." Jonathan Snook ("Evolving guide to CSS architecture for sites small and large." )
  42. Definiendo vistas

  43. Sproutcore / Ember-touch Librería para reconocer diferentes gestos (Influencia iOS

    UIKit) view = Em.View.create({ swipeOptions: { direction: Em.OneGestureDirection.Right, cancelPeriod: cancelPeriod, swipeThreshold: swipeThreshold, simultaneously: true }, swipeStart: function(recognizer) { }, swipeChange: function(recognizer) {}, swipeEnd: function(recognizer) {}, swipeCancel: function(recognizer) {} });
  44. Gestionando los estados Relacionando los estados con la vistas principales

    App.GiftManager = Ember.StateManager.extend({ initialState: 'brand', brand: App.GiftBrandState.create(), city: App.GiftCityState.create(), product: App.GiftProductState.create(), product_info: App.GiftProductInfoState.create(), map: App.GiftMapState.create(), map_error: App.GiftMapErrorState.create(), contact: App.GiftContactState.create(), popup: App.GiftPopupState.create() });
  45. Herramientas de construcción rake-pipeline + makefile Minimizar código Compilar Pre-procesadores

    CSS Empaquetar ficheros Carga asíncrono de librerías/JS Cargar scripts en el orden adecuado …
  46. Siguientes pasos Incluir nuevos patrones Incrementar la adopción y comunidad

    Soporte para distintos navegadores/dispositivos móviles ...
  47. @ppcano @ppcanojr ¡Gracias!