Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

The road to Ember 2.0

Wird geladen in …3

Hier ansehen

1 von 47 Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Ähnlich wie The road to Ember 2.0 (20)


Aktuellste (20)

The road to Ember 2.0

  1. 1. THE ROAD TO EMBER 2.0 FIRST EMBER.JS TREVISO MEETUP presented by /Filippo Zanella @r4m
  2. 2. HURRY UP! On July 24th Ember.js will bump to version 2.0. The core team is moving fast (one release per monthly sprint) Apr 4th v1.11.1, May 13th v1.12, June 12th v1.13.
  3. 3. ...BUT DON'T BE SCARED. Version 2.0 marks the transformation of Ember from simply an MVC framework to a complete front-end stack. Luckily, Ember 2.0 is not a big-bang rewrite. Staying on the cutting-edge can be done without rewriting your app. Changes have been rolled out incrementally. The 2.0 release will simply remove features that have been deprecated.
  5. 5. STABILITY WITHOUT STAGNATION In the greater JavaScript community, getting the latest and greatest often means rewriting parts of your apps once a year. The Ember community works hard to introduce new ideas with an eye towards migration. The Ember core-team call this "stability without stagnation". When breaking changes are absolutely necessary, they try to make those changes ones you can apply without too much thought. They call these "mechanical" refactors. To further aid in these transitions, a new tab to the Ember Inspector that will list all deprecations in your application.
  6. 6. BIG BETS The first bet was on open standards: JavaScript modules, promises and Web Components. The second bet was that the community was tired of hand-rolling their own build scripts for each project. They've invested heavily in Ember CLI, giving us a single tool that unifies the community and provides a venue for disseminating great ideas. In Ember 2.0, Ember CLI and ES6 modules will become first-class parts of the Ember experience. That is, you should begin moving your app to Ember CLI now.
  7. 7. LEARNING FROM COMMUNITY Ember core-team have analyzed and discussing React's approach to data flow and rendering and in particular how they make use of a "virtual DOM" to improve performance. Ember's view layer is one of the oldest parts of Ember, and was designed for a world where IE7 and IE8 were dominant (gosh!). They've spent the better part of 2014 rethinking the view layer to be more DOM-aware, and the new codebase (codenamed "HTMLBars") borrows the best ideas from React. React's "virtual DOM" abstraction also allowed them to simplify the programming model of component-based applications. In Ember 2.0, a "virtual DOM" and data flow model has been adopted to simplifies communication between components.
  8. 8. SIMPLIFYING EMBER CONCEPTS Ember 2.0 is about simplification, to reduce file sizes, reduce code complexity, and generally make apps easier to maintain. The high-level set of improvements that we have planned are: More intuitive attribute bindings New HTML syntax for components Block parameters for components More consistent template scope 1-way data binding by default, with opt-in to 2-way bindings More explicit communication between components Routes drive components, instead of controller + template Improved actions that are invoked inside components
  10. 10. INLINE IF In v1.11 Ember's ifhelper can be used in the inline form: {{if isEnabled 'active' 'disabled'}}
  11. 11. EACH WITH INDEX The eachhelper will support an indexblock param in v1.11: {{#each people as |person index|}} {{!-- The first index value will be 0 --}} <div>{{index}}: {{person.name}}</div> {{/each}}
  12. 12. BOUND ATTRIBUTE SYNTAX Current Ember developers are familiar with the bind-attr syntax, used to declare an attribute binding on an HTML element. <a {{bind-attr href=url}}>Click here</a> Ember 1.11 introduces a more intuitive API for attribute binding. For example, here the color variable is bound to the class of a div: <div class="{{color}}"></div> The inline if helper can also be used in these contexts: <div class="{{color}} {{if isEnabled 'active' 'disabled'}}"></div> For some attributes, like the disabled boolean, passing a literal value is desirable. An example: <input disabled={{isDisabled}}>
  13. 13. COMPONENT HELPER Ember components can be bound via the componenthelper. For example this logic in a template: {{#if isRed}} {{x-red}} {{else if isBlue}} {{x-blue}} {{else if isGreen}} {{x-green}} {{/if}} Can be replaced by a property and the componenthelper. {{component colorComponentName}} The property colorComponentNameshould either have a value of x-red, or x-blueetc. As the value of the computed property changes, the rendered component will also change.
  14. 14. STORE.UNLOADALL() Previously, store.unloadAllrequired a modelNameargument to unload records of a type. Now, you can unload all records without calling store.destroy. @store.unloadAll()can now unload all models when not passed a model name.
  15. 15. GLIMMER Ember 1.13 is the first release that includes the new Glimmer rendering engine. Glimmer is: A new faster rendering engine that is especially fast at updates. An implementation of the React-inspired "just re-render it" programming model for components, with one-way data flow by default and better enforcement for data-down, actions-up. Supports ergonomic attributes (<my-link href=" {{url}}.html">go home</my-link>), angle-bracket components (<my-component />), that hews closely to HTML syntax with a few small enhancements.
  16. 16. THE ATTRSPROPERTY Beginning with Ember 1.13 a component's attributes will be available in this.attrsrather than on the component itself. So when a component is invoked this way: {{my-component title=model.name}} The component will see this.attrs.titleas the current value of model.name. Whenever model.namechanges via observation, or when the parent component is re-rendered, my- component's lifecycle hooks will be triggered, and it will see a new version of model.name.
  17. 17. THE MUTHELPER What if you want to allow the child component to modify the property explicitly? The muthelper will produce an object that contains both a valueproperty and an updatemethod. In Ember 1.13, you can write: {{my-counter count=(mut activatedCount)}} Component.extend click: -> this.attrs.count.update(this.attrs.count.value + 1) The call to {{mut activatedCount}}packages up an object containing both its current value and a callback that allows the receiving component to modify it.
  18. 18. CLOSURE ACTION In Ember 1.x, the actions system used bubbling to pass user behavior to a parent scope. E.g., when clicking a button an action might bubble through several controllers. Action bubbling was difficult to debug, and plagued by an inability to have a return value. Ember 2.x is component-driven, and replaces action bubbling with a function-passing solution. Actions: Can be passed multiple arguments Return a value. E.g. result = this.attrs.submit() Can curry
  19. 19. CLOSURE ACTION For example, action submitis passed to my-componentwhere it is called upon click: app/controllers/index.coffee `import Ember from 'ember'` Ember.Controller.extend actions: setName: (name) -> model.set('name', name) {{! app/templates/index.hbs }} {{my-component submit=(action 'setName')}} app/components/my-component.coffee `import Ember from 'ember'` Ember.Component.extend click: -> this.attrs.submit(this.get('name'))
  20. 20. NEW EMBER.JS HELPER API Ember helpers: Represent a single value Do not manage DOM or control flow Can recompute themselves Can optionally access services Do not require a dash app/helpers/full-name.js ` ` Ember.Helper.helper (params, hash) -> return params.join(' ') import Ember from 'ember' {{full-name "Daniel" model.lastName}} {{my-component name=(full-name model.firstName "Smith")}} {{! The following usage would set the model.name to the new full name when my-component calls the submit action. }} {{my-component submit=(action (mut model.name) (full-name model.firstName "Smith"
  22. 22. MORE CONSISTENT HANDLEBARS SCOPE In Ember 1.9, the context-shifting forms of #eachand #withhave been deprecated in favor of the named-parameter forms. {{#each post in posts}} {{!-- the context in here is the same as the outside context, and `post` references the current iteration --}} {{/each}} {{#each posts}} {{!-- the context in here has shifted to the individual post. the outer context is no longer accessible --}} {{/each}} {{#with post as otherPost}} {{!-- the context in here is the same as the outside context --}} {{/with}} {{#with post}} {{!-- the context in here has shifted to the post. the outer context is no longer accessible --}} {{/with}}
  23. 23. MORE CONSISTENT HANDLEBARS SCOPE In Ember 1.12, the inand assyntax are further deprecated in favor of block params syntax. To transition your code to the new syntax, you can change templates that look like this: {{#each people}} <p>{{firstName}} {{lastName}}</p> <p>{{address}}</p> {{/each}} with: {{#each people itemController="abc" as |person|}} <p>{{person.firstName}} {{person.lastName}}</p> <p>{{person.address}}</p> {{/each}}
  24. 24. OBJECTCONTROLLER Experienced Ember users have enjoyed the use of proxying behavior in the Ember.ObjectControllerclass since 1.0. However, this behavior will be removed in Ember 2.0 as the framework migrates to routable components.
  25. 25. OBJECTCONTROLLER To migrate from an explicitly defined object controller, first convert the class definition to inherit from Ember.Controller. E.g.: import Ember from "ember"; // Change: export default Ember.ObjectController.extend({ // To: export default Ember.Controller.extend({ // ... Next update any use of {{modelPropertyName}}in templates with {{model.modelPropertyName}}. You should also review any computed property dependent keys, observer keys, and get and setstatements on the route and controller.
  26. 26. INSTANCES INITIALIZERS Before FastBoot, you would only ever run applications one at a time. In FastBoot, it is important for a single node server to be able to serve a second request while the first one is fetching its data. In Ember.js 1.12 application boot is separated into two phases: Application initializers run, to register dependencies and injections. These initializers are doing work that is shared across all FastBoot requests, and therefore should not create instances. Instance initializers run next. This is the right time to do work that is specific to each FastBoot request. You can create instances and modify their state here.
  27. 27. ACCESS TO INSTANCES IN INITIALIZERS Previously, initializers had access to an object that allowed them to both register new classes and get instances of those classes. If you have an initializer that gets instances of a class, you need to change it to use an instance initializer. The store service is now injected as an . As a consequence, if you had initializers depending on the store, you should move them to an instance initializer as well, and mark it as after: 'ember-data'. instanceInitializer
  28. 28. ACCESS TO INSTANCES IN INITIALIZERS Change code that looks like this: App.initializer name: "clock" initialize: (container, application) -> application.register("clock:main", Clock) clock = container.lookup("clock:main") clock.setStartTime(Date.now()) To: App.initializer name: "clock" initialize: (registry, application) -> application.register("clock:main", Clock) App.instanceInitializer name: "clock" initialize: (instance) -> clock = instance.container.lookup("clock:main") clock.setStartTime(Date.now())
  29. 29. SHARED GETTER AND SETTER Ember.js 1.12 introduces an improved syntax for computed properties with a setter. Previously, computed properties with a setter implemented that setter by inspecting the number of arguments passed to the computed property's descriptor. For example, this computed property splits a full name into two parts when set: fullName: Ember.computed "firstName", "lastName", (key, newName) -> if (arguments.length > 1) parts = newName.split(" ") this.setProperties({ firstName: parts[0], lastName: parts[1] }) return newName else return this.get("firstName") + " " + this.get("lastName")
  30. 30. SHARED GETTER AND SETTER These uses should be converted to use the new discrete getter and setter syntax introduced in 1.12: fullName: Ember.computed("firstName", "lastName", { get: function() { return this.get("firstName") + " " + this.get("lastName"); }, set: function(key, newName) { var parts = newName.split(" "); this.setProperties({ firstName: parts[0], lastName: parts[1] }); return newName; } });
  31. 31. EMBER.VIEW Ember 1.x encouraged a Model-View-Controller-Route architecture. Since then, the web has consolidated around a Model-Component- Route pattern for web development that Ember 2.0 also embraces. Views are removed from the Ember 2.0 API. YES, VIEWS ARE REMOVED. However a single release is likely insufficient for large apps to upgrade their entire codebase away from routeable views, and consequently Ember is providing extended support for views via the addon. This addon will remain compatible with Ember until v2.4 of the framework is released. ember-legacy-views
  32. 32. EMBER.VIEW In most cases Ember views can be replaced with a component. E.g.: app/templates/show-menu.hbs {{view.title}} app/views/show-menu.coffee ` ` # Usage: {{view "show-menu"}} Ember.View.extend templateName: 'some-menu' title: 'My Menu' import Ember from 'ember' Can be replaced with this component: app/templates/components/show-menu.hbs {{title}} app/components/show-menu.coffee ` ` # Usage: {{show-menu}} Ember.Component.extend title: 'My Menu' import Ember from 'ember'
  33. 33. EMBER.VIEW Note that a component has always its own context in a template. A view's template may have had access to other variables that were present where it was called, such as a controller. A component template will always be isolated, and if data is needed it should be passed upon invocation. For example: {{show-menu options=controller.menuOptions}}
  34. 34. EMBER.VIEW ROUTABLE VIEWS Currently, when a template for a given route is rendered, if there is a view with the same name that view will also be used. For example this view is attached to the rendered route template: app/router.coffee ` ` Ember.Router.map -> this.route('about') import Ember from 'ember' app/views/about.coffee ` ` Ember.View.extend classNameBindings: ['controller.isActive:active'] import Ember from 'ember'
  35. 35. EMBER.VIEW ROUTABLE VIEWS There are only two reasons a view may be used for a route: To set attribute bindings To attach event handlers To manage all the jquery stuffs You should migrate away from routed views.
  36. 36. EMBER.VIEW ROUTABLE VIEWS For example to attach bindings to an element in the template is sufficient: app/router.coffee ` ` Ember.Router.map -> this.route('about') import Ember from 'ember' app/templates/about.hbs <div class="{{if isActive 'active'}}"> <!-- something something --> </div>
  37. 37. EMBER.VIEW ROUTABLE VIEWS If attaching events or sharing DOM is necessary, consider a component: app/templates/about.hbs {{#active-layout isActive=isActive}} <!-- something something --> {{/active-layout}} app/components/active-layout.js ` ` Ember.Component.extend classNameBindings: ['isActive:active'] click: -> # Handle click import Ember from 'ember'
  38. 38. EMBER.VIEW NOTABLE In preparation for Ember 2.0, 1.13 introduces many deprecations. Some of these include: All view APIs in Ember (Ember.CoreView, Ember.View, Ember.CollectionView, Ember.ContainerView) Options to the {{#eachhelper that trigger a legacy and poorly performing legacy layer. Like: itemView, itemViewClass, tagName, emptyViewand emptyViewClass. The itemControllerargument for {{#each. The viewand viewClassparams for {{outlet}}
  39. 39. EMBER.LINKVIEW As a consequence of the deprecation of Ember.View, many internal views have been ported to component. Ember.LinkView, the class that backs the {{link-to}} helper, have been ported to Ember.LinkComponent. Most uses of Ember.LinkViewcan be directly ported to the Ember.LinkComponentclass.
  40. 40. EMBER.SELECT Using the Ember.Selectglobal and its view helper form ({{view 'select'}}) is deprecated. Ember.Selectis implemented in a legacy coding style that uses patterns such as observers and two-way data binding that: can cause pathological performance problems provide an experience that is not consistent with idiomatic Ember 2.0 development. Sadly true. Complex Ember.Selectwith mixed dynamic content are tricky to be managed. Legacy support will be provided via the addon.ember-legacy-views
  41. 41. EMBER.SELECT Ember 2.0 provides several new features that make it much more straightforward to implement </select>tag functionality via the data-down, actions-up paradigm in one's codebase. For example, to create a component that displays a prompt and a list of dropdown options, the following code could be used: app/templates/components/my-select.hbs <select {{action 'change' on='change'}}> {{#each content key="@index" as |item|}} <option value="{{item}}" selected={{is-equal item selectedValue}}> {{item}} </option> {{/each}} </select>
  42. 42. EMBER.SELECT app/components/my-select.js ` ` Ember.Component.extend content: [] selectedValue: null actions: change: -> changeAction = this.get('action') selectedElement = this.$('select')[0] selectedIndex = selectedElement.selectedIndex content = this.get('content') selectedValue = content[selectedIndex] this.set('selectedValue', selectedValue) changeAction(selectedValue) import Ember from 'ember' app/helpers/is-equal.js ` ` Ember.Helper.helper ([leftSide, rightSide]) -> return leftSide === rightSide import Ember from 'ember'
  43. 43. EMBER.SELECT This component could be used in a template by supplying it an array of strings as contentand an action to call when the user makes a selection as change: app/templates/application.hbs The currently selected item: {{mySelectedItem}}. {{my-select content=myItems action=(action (mut mySelectedItem))}} myItemsis an array of strings: ['one', 'two', ...]. This uses the `action`and `mut`helpers to pass in an action that will update the (outer scope) `mySelectedItem`property with the user's selection.
  44. 44. TYPEKEY TO MODELNAME In Ember Data, when you ask for a model, Ember Data looks its class up using Ember's API. When the model class is looked up, Ember Data stores the type on the model class. Dependency Injection For example, when the following code runs in your application: post = this.store.getById('post', 1) and Ember Data will store the string "post" on the model class: console.log(post.constructor.typeKey) # 'post' Ember Data uses this typeKeyproperty internally when creating/extracting payloads in Serializers, and when locating models in Adapters.
  45. 45. TYPEKEY TO MODELNAME In Ember Data 1.0.0-beta.18, the typeKeyproperty is now called modelName. In addition, the modelNameis a dasherized string (previously it was always normalized to be a camelCased string). For example, if you had a model called TacoShop, it would be stored on the model's constructor's modelName property as taco-shop, whereas previously it would be stored as tacoShop. Accessing the typeKeyproperty should still work, but will trigger deprecation warnings.
  46. 46. IE 8 Ember Data v1.0.0-beta.19 is the last release to support Internet Explorer 8. Future versions of Ember Data will not support IE 8. R.I.P.
  47. 47. RESOURCES The road to Ember.js 2.0 RFC The transition to Ember 2.0 in detail Deprecations added in Ember 1.X